2 parted - a frontend to libparted
3 Copyright (C) 1999, 2000, 2001, 2002, 2003, 2005, 2006
4 Free Software Foundation, Inc.
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include "../config.h"
26 #define N_(String) String
30 # define _(String) dgettext (PACKAGE, String)
32 # define _(String) (String)
33 #endif /* ENABLE_NLS */
35 #include <parted/parted.h>
36 #include <parted/debug.h>
51 /* minimum amount of free space to leave, or maximum amount to gobble up */
52 #define MIN_FREESPACE (1000 * 2) /* 1000k */
54 static int MEGABYTE_SECTORS (PedDevice* dev)
56 return PED_MEGABYTE_SIZE / dev->sector_size;
62 time_t predicted_time_left;
65 static struct option options[] = {
66 /* name, has-arg, string-return-val, char-return-val */
67 {"help", 0, NULL, 'h'},
68 {"interactive", 0, NULL, 'i'},
69 {"list", 0, NULL, 'l'},
70 {"script", 0, NULL, 's'},
71 {"version", 0, NULL, 'v'},
76 static char* options_help [][2] = {
77 {"help", N_("displays this help message")},
78 {"interactive", N_("where necessary, prompts for user intervention")},
79 {"list", N_("lists partition tables of all detected devices")},
80 {"script", N_("never prompts for user intervention")},
81 {"version", N_("displays the version")},
86 int is_toggle_mode = 0;
88 static char* number_msg = N_(
89 "NUMBER is the partition number used by Linux. On MS-DOS disk labels, the "
90 "primary partitions number from 1 to 4, logical partitions from 5 onwards.\n");
92 static char* label_type_msg_start = N_("LABEL-TYPE is one of: ");
93 static char* flag_msg_start = N_("FLAG is one of: ");
94 static char* unit_msg_start = N_("UNIT is one of: ");
95 static char* part_type_msg = N_("PART-TYPE is one of: primary, logical, "
97 static char* fs_type_msg_start = N_("FS-TYPE is one of: ");
98 static char* start_end_msg = N_("START and END are disk locations, such as "
99 "4GB or 10%. Negative values count from the end of the disk. "
100 "For example, -1s specifies exactly the last sector.\n");
101 static char* state_msg = N_("STATE is one of: on, off\n");
102 static char* device_msg = N_("DEVICE is usually /dev/hda or /dev/sda\n");
103 static char* name_msg = N_("NAME is any word you want\n");
104 static char* resize_msg_start = N_("The partition must have one of the "
105 "following FS-TYPEs: ");
107 static char* version_msg = N_("GNU Parted Version information:\n");
108 static char* copyright_msg = N_(
109 "Copyright (C) 1998 - 2006 Free Software Foundation, Inc.\n"
110 "This program is free software, covered by the GNU General Public License.\n"
112 "This program is distributed in the hope that it will be useful, "
113 "but WITHOUT ANY WARRANTY; without even the implied warranty of "
114 "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the "
115 "GNU General Public License for more details.\n\n");
117 static char* label_type_msg;
118 static char* flag_msg;
119 static char* unit_msg;
121 static char* mkfs_fs_type_msg;
122 static char* mkpart_fs_type_msg;
123 static char* resize_fs_type_msg;
125 static Command* commands [256] = {NULL};
126 static PedTimer* timer;
127 static TimerContext timer_context;
129 static int _print_all (int cli);
130 static void _done (PedDevice* dev);
133 _timer_handler (PedTimer* timer, void* context)
135 TimerContext* tcontext = (TimerContext*) context;
138 if (opt_script_mode || !isatty(fileno(stdout)))
141 if (tcontext->last_update != timer->now && timer->now > timer->start) {
142 tcontext->predicted_time_left
143 = timer->predicted_end - timer->now;
144 tcontext->last_update = timer->now;
150 if (draw_this_time) {
153 if (timer->state_name)
154 printf ("%s... ", timer->state_name);
155 printf (_("%0.f%%\t(time left %.2d:%.2d)"),
157 tcontext->predicted_time_left / 60,
158 tcontext->predicted_time_left % 60);
165 _partition_warn_busy (PedPartition* part)
169 if (ped_partition_is_busy (part)) {
170 path = ped_partition_get_path (part);
171 ped_exception_throw (
173 PED_EXCEPTION_CANCEL,
174 _("Partition %s is being used. You must unmount it "
175 "before you modify it with Parted."),
184 _disk_warn_busy (PedDisk* disk)
186 if (ped_device_is_busy (disk->dev))
187 return ped_exception_throw (
188 PED_EXCEPTION_WARNING,
189 PED_EXCEPTION_IGNORE_CANCEL,
190 _("Partition(s) on %s are being used."),
192 == PED_EXCEPTION_IGNORE;
198 _partition_warn_loss ()
200 return ped_exception_throw (
201 PED_EXCEPTION_WARNING,
202 PED_EXCEPTION_YES_NO,
203 _("The existing file system will be destroyed and "
204 "all data on the partition will be lost. Do "
205 "you want to continue?"),
206 NULL) == PED_EXCEPTION_YES;
210 _disk_warn_loss (PedDisk* disk)
212 return ped_exception_throw (
213 PED_EXCEPTION_WARNING,
214 PED_EXCEPTION_YES_NO,
215 _("The existing disk label on %s will be destroyed "
216 "and all data on this disk will be lost. Do you "
217 "want to continue?"),
219 == PED_EXCEPTION_YES;
222 /* This function changes "sector" to "new_sector" if the new value lies
223 * within the required range.
226 snap (PedSector* sector, PedSector new_sector, PedGeometry* range)
228 PED_ASSERT (ped_geometry_test_sector_inside (range, *sector), return 0);
229 if (!ped_geometry_test_sector_inside (range, new_sector))
231 *sector = new_sector;
242 enum { /* Don't change these values */
247 /* Find the prefered way to adjust the sector s inside range.
248 * If a move isn't allowed or is out of range it can't be selected.
249 * what contains SECT_START if the sector to adjust is a start sector
250 * or SECT_END if it's an end one.
251 * The prefered move is to the nearest allowed boundary of the part
252 * partition (if at equal distance: to start if SECT_START or to end
254 * The distance is returned in dist.
257 prefer_snap (PedSector s, int what, PedGeometry* range, EMoves* allow,
258 PedPartition* part, PedSector* dist)
260 PedSector up_dist = -1, down_dist = -1;
264 PED_ASSERT (what == SECT_START || what == SECT_END, return 0);
266 if (!(*allow & (MOVE_UP | MOVE_DOWN))) {
271 if (*allow & MOVE_UP) {
272 new_sect = part->geom.end + 1 + what;
273 if (ped_geometry_test_sector_inside (range, new_sect))
274 up_dist = new_sect - s;
279 if (*allow & MOVE_DOWN) {
280 new_sect = part->geom.start + what;
281 if (ped_geometry_test_sector_inside (range, new_sect))
282 down_dist = s - new_sect;
284 *allow &= ~MOVE_DOWN;
288 if ((*allow & MOVE_UP) && (*allow & MOVE_DOWN)) {
289 if (down_dist < up_dist || (down_dist == up_dist
290 && what == SECT_START) )
292 else if (up_dist < down_dist || (down_dist == up_dist
293 && what == SECT_END) )
296 PED_ASSERT (0, return 0);
297 } else if (*allow & MOVE_UP)
299 else if (*allow & MOVE_DOWN)
302 *dist = ( move == MOVE_DOWN ? down_dist :
303 ( move == MOVE_UP ? up_dist :
308 /* Snaps a partition to nearby partition boundaries. This is useful for
309 * gobbling up small amounts of free space, and also for reinterpreting small
310 * changes to a partition as non-changes (eg: perhaps the user only wanted to
311 * resize the end of a partition).
312 * Note that this isn't the end of the story... this function is
313 * always called before the constraint solver kicks in. So you don't need to
314 * worry too much about inadvertantly creating overlapping partitions, etc.
317 snap_to_boundaries (PedGeometry* new_geom, PedGeometry* old_geom,
319 PedGeometry* start_range, PedGeometry* end_range)
321 PedPartition* start_part;
322 PedPartition* end_part;
323 PedSector start = new_geom->start;
324 PedSector end = new_geom->end;
325 PedSector start_dist = -1, end_dist = -1;
326 EMoves start_allow, end_allow, start_want, end_want;
329 start_want = end_want = MOVE_NO;
330 start_allow = end_allow = MOVE_STILL | MOVE_UP | MOVE_DOWN;
332 start_part = ped_disk_get_partition_by_sector (disk, start);
333 end_part = ped_disk_get_partition_by_sector (disk, end);
334 adjacent = (start_part->geom.end + 1 == end_part->geom.start);
336 /* If we can snap to old_geom, then we will... */
337 /* and this will enforce the snapped positions */
339 if (snap (&start, old_geom->start, start_range))
340 start_allow = MOVE_STILL;
341 if (snap (&end, old_geom->end, end_range))
342 end_allow = MOVE_STILL;
345 /* If start and end are on the same partition, we */
346 /* don't allow them to cross. */
347 if (start_part == end_part) {
348 start_allow &= ~MOVE_UP;
349 end_allow &= ~MOVE_DOWN;
352 /* Let's find our way */
353 start_want = prefer_snap (start, SECT_START, start_range, &start_allow,
354 start_part, &start_dist );
355 end_want = prefer_snap (end, SECT_END, end_range, &end_allow,
356 end_part, &end_dist );
358 PED_ASSERT (start_dist >= 0 && end_dist >= 0, return);
360 /* If start and end are on adjacent partitions, */
361 /* and if they would prefer crossing, then refrain */
362 /* the farthest to do so. */
363 if (adjacent && start_want == MOVE_UP && end_want == MOVE_DOWN) {
364 if (end_dist < start_dist) {
365 start_allow &= ~MOVE_UP;
366 start_want = prefer_snap (start, SECT_START,
367 start_range, &start_allow,
368 start_part, &start_dist );
369 PED_ASSERT (start_dist >= 0, return);
371 end_allow &= ~MOVE_DOWN;
372 end_want = prefer_snap (end, SECT_END,
373 end_range, &end_allow,
374 end_part, &end_dist );
375 PED_ASSERT (end_dist >= 0, return);
380 start = ( start_want == MOVE_DOWN ? start_part->geom.start :
381 ( start_want == MOVE_UP ? start_part->geom.end + 1 :
383 end = ( end_want == MOVE_DOWN ? end_part->geom.start - 1 :
384 ( end_want == MOVE_UP ? end_part->geom.end :
386 PED_ASSERT (ped_geometry_test_sector_inside(start_range,start), return);
387 PED_ASSERT (ped_geometry_test_sector_inside (end_range, end), return);
388 PED_ASSERT (start <= end,
389 PED_DEBUG (0, "start = %d, end = %d\n", start, end));
390 ped_geometry_set (new_geom, start, end - start + 1);
393 /* This functions constructs a constraint from the following information:
394 * start, is_start_exact, end, is_end_exact.
396 * If is_start_exact == 1, then the constraint requires start be as given in
397 * "start". Otherwise, the constraint does not set any requirements on the
400 static PedConstraint*
401 constraint_from_start_end (PedDevice* dev, PedGeometry* range_start,
402 PedGeometry* range_end)
404 return ped_constraint_new (ped_alignment_any, ped_alignment_any,
405 range_start, range_end, 1, dev->length);
408 static PedConstraint*
409 constraint_intersect_and_destroy (PedConstraint* a, PedConstraint* b)
411 PedConstraint* result = ped_constraint_intersect (a, b);
412 ped_constraint_destroy (a);
413 ped_constraint_destroy (b);
418 help_on (char* topic)
422 cmd = command_get (commands, topic);
425 command_print_help (cmd);
429 do_check (PedDevice** dev)
433 PedPartition* part = NULL;
436 disk = ped_disk_new (*dev);
440 if (!command_line_get_partition (_("Partition number?"), disk, &part))
441 goto error_destroy_disk;
442 if (!_partition_warn_busy (part))
443 goto error_destroy_disk;
445 if (!ped_disk_check (disk))
446 goto error_destroy_disk;
448 fs = ped_file_system_open (&part->geom);
450 goto error_destroy_disk;
451 if (!ped_file_system_check (fs, timer))
453 ped_file_system_close (fs);
454 ped_disk_destroy (disk);
458 ped_file_system_close (fs);
460 ped_disk_destroy (disk);
466 do_cp (PedDevice** dev)
470 PedDevice* src_device;
471 PedPartition* src = NULL;
472 PedPartition* dst = NULL;
473 PedFileSystem* src_fs;
474 PedFileSystem* dst_fs;
475 PedFileSystemType* dst_fs_type;
477 dst_disk = ped_disk_new (*dev);
482 if (!command_line_is_integer ()) {
483 if (!command_line_get_disk (_("Source device?"), &src_disk))
484 goto error_destroy_disk;
487 if (!command_line_get_partition (_("Source partition number?"),
489 goto error_destroy_disk;
490 if (src->type == PED_PARTITION_EXTENDED) {
491 ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
492 _("Can't copy an extended partition."));
493 goto error_destroy_disk;
495 if (!_partition_warn_busy (src))
496 goto error_destroy_disk;
498 if (!command_line_get_partition (_("Destination partition number?"),
500 goto error_destroy_disk;
501 if (!_partition_warn_busy (dst))
502 goto error_destroy_disk;
505 src_fs = ped_file_system_open (&src->geom);
507 goto error_destroy_disk;
508 dst_fs = ped_file_system_copy (src_fs, &dst->geom, timer);
510 goto error_close_src_fs;
511 dst_fs_type = dst_fs->type; /* may be different to src_fs->type */
512 ped_file_system_close (src_fs);
513 ped_file_system_close (dst_fs);
515 /* update the partition table, close disks */
516 if (!ped_partition_set_system (dst, dst_fs_type))
517 goto error_destroy_disk;
518 if (!ped_disk_commit (dst_disk))
519 goto error_destroy_disk;
520 if (src_disk != dst_disk)
521 ped_disk_destroy (src_disk);
522 ped_disk_destroy (dst_disk);
526 ped_file_system_close (src_fs);
528 if (src_disk && src_disk != dst_disk)
529 ped_disk_destroy (src_disk);
530 ped_disk_destroy (dst_disk);
536 print_commands_help ()
540 for (i=0; commands [i]; i++)
541 command_print_summary (commands [i]);
545 print_options_help ()
549 for (i=0; options_help [i][0]; i++) {
550 printf (" -%c, --%-23.23s %s\n",
551 options_help [i][0][0],
553 _(options_help [i][1]));
558 do_help (PedDevice** dev)
560 if (command_line_get_word_count ()) {
561 char* word = command_line_pop_word ();
567 print_commands_help();
573 do_mklabel (PedDevice** dev)
576 const PedDiskType* type = ped_disk_probe (*dev);
578 ped_exception_fetch_all ();
579 disk = ped_disk_new (*dev);
580 if (!disk) ped_exception_catch ();
581 ped_exception_leave_all ();
583 if (!_disk_warn_loss (disk))
584 goto error_destroy_disk;
587 if (!_disk_warn_busy (disk))
588 goto error_destroy_disk;
589 ped_disk_destroy (disk);
592 if (!command_line_get_disk_type (_("New disk label type?"), &type))
595 disk = ped_disk_new_fresh (*dev, type);
599 if (!ped_disk_commit (disk))
600 goto error_destroy_disk;
601 ped_disk_destroy (disk);
605 ped_disk_destroy (disk);
611 do_mkfs (PedDevice** dev)
614 PedPartition* part = NULL;
615 const PedFileSystemType* type = ped_file_system_type_get ("ext2");
618 disk = ped_disk_new (*dev);
622 if (!_partition_warn_loss())
623 goto error_destroy_disk;
625 if (!command_line_get_partition (_("Partition number?"), disk, &part))
626 goto error_destroy_disk;
627 if (!_partition_warn_busy (part))
628 goto error_destroy_disk;
629 if (!command_line_get_fs_type (_("File system?"), &type))
630 goto error_destroy_disk;
632 fs = ped_file_system_create (&part->geom, type, timer);
634 goto error_destroy_disk;
635 ped_file_system_close (fs);
637 if (!ped_partition_set_system (part, type))
638 goto error_destroy_disk;
639 if (ped_partition_is_flag_available (part, PED_PARTITION_LBA))
640 ped_partition_set_flag (part, PED_PARTITION_LBA, 1);
641 if (!ped_disk_commit (disk))
642 goto error_destroy_disk;
643 ped_disk_destroy (disk);
647 ped_disk_destroy (disk);
653 do_mkpart (PedDevice** dev)
657 PedPartitionType part_type;
658 const PedFileSystemType* fs_type = ped_file_system_type_get ("ext2");
659 PedSector start = 0, end = 0;
660 PedGeometry *range_start = NULL, *range_end = NULL;
661 PedConstraint* user_constraint;
662 PedConstraint* dev_constraint;
663 PedConstraint* final_constraint;
665 char* part_name = NULL;
666 char *start_usr = NULL, *end_usr = NULL;
667 char *start_sol = NULL, *end_sol = NULL;
669 disk = ped_disk_new (*dev);
673 if (!ped_disk_type_check_feature (disk->type, PED_DISK_TYPE_EXTENDED)) {
674 part_type = PED_PARTITION_NORMAL;
676 if (!command_line_get_part_type (_("Partition type?"),
678 goto error_destroy_disk;
681 if (ped_disk_type_check_feature (disk->type,
682 PED_DISK_TYPE_PARTITION_NAME))
683 part_name = command_line_get_word (_("Partition name?"),
686 peek_word = command_line_peek_word ();
687 if (part_type == PED_PARTITION_EXTENDED
688 || (peek_word && isdigit (peek_word[0]))) {
691 if (!command_line_get_fs_type (_("File system type?"),
693 goto error_destroy_disk;
696 ped_free (peek_word);
698 if (!command_line_get_sector (_("Start?"), *dev, &start, &range_start))
699 goto error_destroy_disk;
700 if (!command_line_get_sector (_("End?"), *dev, &end, &range_end))
701 goto error_destroy_disk;
703 /* processing starts here */
704 part = ped_partition_new (disk, part_type, fs_type, start, end);
706 goto error_destroy_disk;
708 snap_to_boundaries (&part->geom, NULL, disk, range_start, range_end);
710 /* create constraints */
711 user_constraint = constraint_from_start_end (*dev, range_start,
713 PED_ASSERT (user_constraint != NULL, return 0);
715 dev_constraint = ped_device_get_constraint (*dev);
716 PED_ASSERT (dev_constraint != NULL, return 0);
718 final_constraint = ped_constraint_intersect (user_constraint,
720 if (!final_constraint)
721 goto error_destroy_simple_constraints;
723 /* subject to partition constraint */
724 ped_exception_fetch_all();
725 if (!ped_disk_add_partition (disk, part, final_constraint)) {
726 ped_exception_leave_all();
728 if (ped_disk_add_partition (disk, part,
729 ped_constraint_any (*dev))) {
730 start_usr = ped_unit_format (*dev, start);
731 end_usr = ped_unit_format (*dev, end);
732 start_sol = ped_unit_format (*dev, part->geom.start);
733 end_sol = ped_unit_format (*dev, part->geom.end);
735 switch (ped_exception_throw (
736 PED_EXCEPTION_WARNING,
737 PED_EXCEPTION_YES_NO,
738 _("You requested a partition from %s to %s.\n"
739 "The closest location we can manage is "
741 "Is this still acceptable to you?"),
742 start_usr, end_usr, start_sol, end_sol))
744 case PED_EXCEPTION_YES:
745 /* all is well in this state */
747 case PED_EXCEPTION_NO:
748 case PED_EXCEPTION_UNHANDLED:
750 /* undo partition addition */
751 goto error_remove_part;
754 goto error_remove_part;
757 ped_exception_catch();
759 /* set minor attributes */
761 PED_ASSERT (ped_partition_set_name (part, part_name), return 0);
762 if (!ped_partition_set_system (part, fs_type))
763 goto error_destroy_disk;
764 if (ped_partition_is_flag_available (part, PED_PARTITION_LBA))
765 ped_partition_set_flag (part, PED_PARTITION_LBA, 1);
767 if (!ped_disk_commit (disk))
768 goto error_destroy_disk;
771 ped_constraint_destroy (final_constraint);
772 ped_constraint_destroy (user_constraint);
773 ped_constraint_destroy (dev_constraint);
775 ped_disk_destroy (disk);
777 if (range_start != NULL)
778 ped_geometry_destroy (range_start);
779 if (range_end != NULL)
780 ped_geometry_destroy (range_end);
782 if (start_usr != NULL)
783 ped_free (start_usr);
786 if (start_sol != NULL)
787 ped_free (start_sol);
794 ped_disk_remove_partition (disk, part);
795 error_destroy_all_constraints:
796 ped_constraint_destroy (final_constraint);
797 error_destroy_simple_constraints:
798 ped_constraint_destroy (user_constraint);
799 ped_constraint_destroy (dev_constraint);
801 ped_partition_destroy (part);
803 ped_disk_destroy (disk);
805 if (range_start != NULL)
806 ped_geometry_destroy (range_start);
807 if (range_end != NULL)
808 ped_geometry_destroy (range_end);
810 if (start_usr != NULL)
811 ped_free (start_usr);
814 if (start_sol != NULL)
815 ped_free (start_sol);
823 do_mkpartfs (PedDevice** dev)
827 PedPartitionType part_type;
828 const PedFileSystemType* fs_type = ped_file_system_type_get ("ext2");
829 PedSector start = 0, end = 0;
830 PedGeometry *range_start = NULL, *range_end = NULL;
831 PedConstraint* user_constraint;
832 PedConstraint* dev_constraint;
833 PedConstraint* final_constraint;
835 char* part_name = NULL;
836 char *start_usr = NULL, *end_usr = NULL;
837 char *start_sol = NULL, *end_sol = NULL;
839 disk = ped_disk_new (*dev);
843 if (!ped_disk_type_check_feature (disk->type, PED_DISK_TYPE_EXTENDED)) {
844 part_type = PED_PARTITION_NORMAL;
846 if (!command_line_get_part_type (_("Partition type?"),
848 goto error_destroy_disk;
851 if (ped_disk_type_check_feature (disk->type,
852 PED_DISK_TYPE_PARTITION_NAME))
853 part_name = command_line_get_word (_("Partition name?"),
856 if (part_type == PED_PARTITION_EXTENDED) {
857 ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
858 _("An extended partition cannot hold a file system. "
859 "Did you want mkpart?"));
860 goto error_destroy_disk;
863 if (!command_line_get_fs_type (_("File system type?"), &fs_type))
864 goto error_destroy_disk;
865 if (!command_line_get_sector (_("Start?"), *dev, &start,
867 goto error_destroy_disk;
868 if (!command_line_get_sector (_("End?"), *dev, &end, &range_end))
869 goto error_destroy_disk;
871 /* attempt to create the partition now */
872 part = ped_partition_new (disk, part_type, fs_type, start, end);
874 goto error_destroy_disk;
876 snap_to_boundaries (&part->geom, NULL, disk, range_start, range_end);
878 /* create constraints */
879 user_constraint = constraint_from_start_end (*dev, range_start,
881 PED_ASSERT (user_constraint != NULL, return 0);
883 dev_constraint = ped_device_get_constraint (*dev);
884 PED_ASSERT (dev_constraint != NULL, return 0);
886 final_constraint = ped_constraint_intersect (user_constraint,
888 if (!final_constraint)
889 goto error_destroy_simple_constraints;
891 /* subject to partition constraint */
892 ped_exception_fetch_all();
893 if (!ped_disk_add_partition (disk, part, final_constraint)) {
894 ped_exception_leave_all();
896 if (ped_disk_add_partition (disk, part,
897 ped_constraint_any (*dev))) {
898 start_usr = ped_unit_format (*dev, start);
899 end_usr = ped_unit_format (*dev, end);
900 start_sol = ped_unit_format (*dev, part->geom.start);
901 end_sol = ped_unit_format (*dev, part->geom.end);
903 switch (ped_exception_throw (
904 PED_EXCEPTION_WARNING,
905 PED_EXCEPTION_YES_NO,
906 _("You requested a partition from %s to %s.\n"
907 "The closest location we can manage is "
909 "Is this still acceptable to you?"),
910 start_usr, end_usr, start_sol, end_sol)) {
911 case PED_EXCEPTION_YES:
912 /* all is well in this state */
914 case PED_EXCEPTION_NO:
915 case PED_EXCEPTION_UNHANDLED:
917 /* undo partition addition */
918 goto error_remove_part;
921 goto error_remove_part;
924 ped_exception_catch();
926 /* set LBA flag automatically if available */
927 if (ped_partition_is_flag_available (part, PED_PARTITION_LBA))
928 ped_partition_set_flag (part, PED_PARTITION_LBA, 1);
931 fs = ped_file_system_create (&part->geom, fs_type, timer);
933 goto error_destroy_disk;
934 ped_file_system_close (fs);
936 if (!ped_partition_set_system (part, fs_type))
937 goto error_destroy_disk;
939 if (!ped_disk_commit (disk))
940 goto error_destroy_disk;
943 ped_constraint_destroy (final_constraint);
944 ped_constraint_destroy (user_constraint);
945 ped_constraint_destroy (dev_constraint);
947 ped_disk_destroy (disk);
949 if (range_start != NULL)
950 ped_geometry_destroy (range_start);
951 if (range_end != NULL)
952 ped_geometry_destroy (range_end);
954 if (start_usr != NULL)
955 ped_free (start_usr);
958 if (start_sol != NULL)
959 ped_free (start_sol);
966 ped_disk_remove_partition (disk, part);
967 error_destroy_all_constraints:
968 ped_constraint_destroy (final_constraint);
969 error_destroy_simple_constraints:
970 ped_constraint_destroy (user_constraint);
971 ped_constraint_destroy (dev_constraint);
973 ped_partition_destroy (part);
975 ped_disk_destroy (disk);
977 if (range_start != NULL)
978 ped_geometry_destroy (range_start);
979 if (range_end != NULL)
980 ped_geometry_destroy (range_end);
982 if (start_usr != NULL)
983 ped_free (start_usr);
986 if (start_sol != NULL)
987 ped_free (start_sol);
995 do_move (PedDevice** dev)
998 PedPartition* part = NULL;
1000 PedFileSystem* fs_copy;
1001 PedConstraint* constraint;
1002 PedSector start = 0, end = 0;
1003 PedGeometry *range_start = NULL, *range_end = NULL;
1004 PedGeometry old_geom, new_geom;
1006 disk = ped_disk_new (*dev);
1010 if (!command_line_get_partition (_("Partition number?"), disk, &part))
1011 goto error_destroy_disk;
1012 if (!_partition_warn_busy (part))
1013 goto error_destroy_disk;
1014 if (part->type == PED_PARTITION_EXTENDED) {
1015 ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
1016 _("Can't move an extended partition."));
1017 goto error_destroy_disk;
1019 old_geom = part->geom;
1020 fs = ped_file_system_open (&old_geom);
1022 goto error_destroy_disk;
1024 /* get new target */
1025 if (!command_line_get_sector (_("Start?"), *dev, &start, &range_start))
1026 goto error_close_fs;
1027 end = start + old_geom.length - 1;
1028 if (!command_line_get_sector (_("End?"), *dev, &end, &range_end))
1029 goto error_close_fs;
1031 /* set / test on "disk" */
1032 if (!ped_geometry_init (&new_geom, *dev, start, end - start + 1))
1033 goto error_close_fs;
1034 snap_to_boundaries (&new_geom, NULL, disk, range_start, range_end);
1036 constraint = constraint_intersect_and_destroy (
1037 ped_file_system_get_copy_constraint (fs, *dev),
1038 constraint_from_start_end(*dev,range_start,range_end));
1039 if (!ped_disk_set_partition_geom (disk, part, constraint,
1040 new_geom.start, new_geom.end))
1041 goto error_destroy_constraint;
1042 ped_constraint_destroy (constraint);
1043 if (ped_geometry_test_overlap (&old_geom, &part->geom)) {
1044 ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
1045 _("Can't move a partition onto itself. Try using "
1046 "resize, perhaps?"));
1047 goto error_close_fs;
1051 fs_copy = ped_file_system_copy (fs, &part->geom, timer);
1053 goto error_close_fs;
1054 ped_file_system_close (fs_copy);
1055 ped_file_system_close (fs);
1056 if (!ped_disk_commit (disk))
1057 goto error_destroy_disk;
1058 ped_disk_destroy (disk);
1059 if (range_start != NULL)
1060 ped_geometry_destroy (range_start);
1061 if (range_end != NULL)
1062 ped_geometry_destroy (range_end);
1065 error_destroy_constraint:
1066 ped_constraint_destroy (constraint);
1068 ped_file_system_close (fs);
1070 ped_disk_destroy (disk);
1072 if (range_start != NULL)
1073 ped_geometry_destroy (range_start);
1074 if (range_end != NULL)
1075 ped_geometry_destroy (range_end);
1080 do_name (PedDevice** dev)
1083 PedPartition* part = NULL;
1086 disk = ped_disk_new (*dev);
1090 if (!command_line_get_partition (_("Partition number?"), disk, &part))
1091 goto error_destroy_disk;
1093 name = command_line_get_word (_("Partition name?"),
1094 ped_partition_get_name (part), NULL, 0);
1096 goto error_destroy_disk;
1097 if (!ped_partition_set_name (part, name))
1098 goto error_free_name;
1101 if (!ped_disk_commit (disk))
1102 goto error_destroy_disk;
1103 ped_disk_destroy (disk);
1109 ped_disk_destroy (disk);
1115 partition_print_flags (PedPartition* part)
1117 PedPartitionFlag flag;
1120 char* res = ped_malloc(1);
1126 for (flag = ped_partition_flag_next (0); flag;
1127 flag = ped_partition_flag_next (flag)) {
1128 if (ped_partition_get_flag (part, flag)) {
1133 ped_realloc (&_res, strlen (res)
1136 strncat (res, ", ", 2);
1139 name = _(ped_partition_flag_get_name (flag));
1141 ped_realloc (&_res, strlen (res) + 1
1144 strncat (res, name, 21);
1151 /* Prints a sector out, first in compact form, and then with a percentage.
1155 print_sector_compact_and_percent (PedSector sector, PedDevice* dev)
1160 if (ped_unit_get_default() == PED_UNIT_PERCENT)
1161 compact = ped_unit_format (dev, sector);
1163 compact = ped_unit_format_custom (dev, sector,
1166 percent = ped_unit_format_custom (dev, sector, PED_UNIT_PERCENT);
1168 printf ("%s (%s)\n", compact, percent);
1175 partition_print (PedPartition* part)
1178 PedConstraint* resize_constraint;
1181 fs = ped_file_system_open (&part->geom);
1187 flags = partition_print_flags (part);
1189 printf (_("Minor: %d\n"), part->num);
1190 printf (_("Flags: %s\n"), flags);
1191 printf (_("File System: %s\n"), fs->type->name);
1192 printf (_("Size: "));
1193 print_sector_compact_and_percent (part->geom.length, part->geom.dev);
1195 resize_constraint = ped_file_system_get_resize_constraint (fs);
1196 if (resize_constraint) {
1197 printf (_("Minimum size: "));
1198 print_sector_compact_and_percent (resize_constraint->min_size,
1200 printf (_("Maximum size: "));
1201 print_sector_compact_and_percent (resize_constraint->max_size,
1203 ped_constraint_destroy (resize_constraint);
1209 ped_file_system_close (fs);
1215 do_print (PedDevice** dev)
1223 int has_num_arg = 0;
1224 int has_free_arg = 0;
1225 int has_all_arg = 0;
1226 char* transport[13] = {"unknown", "scsi", "ide", "dac960",
1227 "cpqarray", "file", "ataraid", "i2o",
1228 "ubd", "dasd", "viodasd", "sx8", "dm"};
1235 wchar_t* table_rendered;
1237 disk = ped_disk_new (*dev);
1241 peek_word = command_line_peek_word ();
1243 has_num_arg = isdigit (peek_word[0]);
1245 if (strncmp (peek_word, "free", 4) == 0) {
1246 command_line_pop_word ();
1250 if (strncmp (peek_word, "all", 3) == 0) {
1251 command_line_pop_word();
1255 ped_free (peek_word);
1260 PedPartition* part = NULL;
1262 if (command_line_get_partition ("", disk, &part))
1263 status = partition_print (part);
1264 ped_disk_destroy (disk);
1269 return _print_all (0);
1271 start = ped_unit_format (*dev, 0);
1272 end = ped_unit_format_byte (*dev, (*dev)->length * (*dev)->sector_size
1275 printf (_("Model: %s (%s)\n"), (*dev)->model, transport[(*dev)->type]);
1276 printf (_("Disk %s: %s\n"), (*dev)->path, end);
1277 printf (_("Sector size (logical/physical): %lldB/%lldB\n"),
1278 (*dev)->sector_size, (*dev)->phys_sector_size);
1282 if (ped_unit_get_default () == PED_UNIT_CHS
1283 || ped_unit_get_default () == PED_UNIT_CYLINDER) {
1284 PedCHSGeometry* chs = &(*dev)->bios_geom;
1285 char* cyl_size = ped_unit_format_custom (*dev,
1286 chs->heads * chs->sectors,
1288 printf (_("BIOS cylinder,head,sector geometry: %d,%d,%d. "
1289 "Each cylinder is %s.\n"),
1290 chs->cylinders, chs->heads, chs->sectors, cyl_size);
1291 ped_free (cyl_size);
1294 printf (_("Partition Table: %s\n"), disk->type->name);
1298 has_extended = ped_disk_type_check_feature (disk->type,
1299 PED_DISK_TYPE_EXTENDED);
1300 has_name = ped_disk_type_check_feature (disk->type,
1301 PED_DISK_TYPE_PARTITION_NAME);
1304 if (ped_unit_get_default() == PED_UNIT_CHS) {
1305 row = str_list_create (_("Number"), _("Start"),
1308 row = str_list_create (_("Number"), _("Start"),
1309 _("End"), _("Size"), NULL);
1313 str_list_append (row, _("Type"));
1315 str_list_append (row, _("File system"));
1318 str_list_append (row, _("Name"));
1320 str_list_append (row, _("Flags"));
1323 table = table_new (str_list_length(row));
1325 table_add_row_from_strlist (table, row);
1328 for (part = ped_disk_next_partition (disk, NULL); part;
1329 part = ped_disk_next_partition (disk, part)) {
1331 if ((!has_free_arg && !ped_partition_is_active(part)) ||
1332 part->type & PED_PARTITION_METADATA)
1335 tmp = ped_malloc (4);
1338 sprintf (tmp, "%2d ", part->num);
1340 sprintf (tmp, "%2s ", "");
1342 row = str_list_create (tmp, NULL);
1344 start = ped_unit_format (*dev, part->geom.start);
1345 end = ped_unit_format_byte (
1346 *dev, (part->geom.end + 1) * (*dev)->sector_size - 1);
1347 size = ped_unit_format (*dev, part->geom.length);
1348 if (ped_unit_get_default() == PED_UNIT_CHS) {
1349 str_list_append (row, start);
1350 str_list_append (row, end);
1352 str_list_append (row, start);
1353 str_list_append (row, end);
1354 str_list_append (row, size);
1357 if (!(part->type & PED_PARTITION_FREESPACE)) {
1359 name = _(ped_partition_type_get_name (part->type));
1360 str_list_append (row, name);
1363 str_list_append (row, part->fs_type ?
1364 part->fs_type->name : "");
1367 name = _(ped_partition_get_name (part));
1368 str_list_append (row, name);
1371 str_list_append (row, partition_print_flags (part));
1374 str_list_append (row, "");
1375 str_list_append (row, _("Free Space"));
1377 str_list_append (row, "");
1378 str_list_append (row, "");
1381 //PED_ASSERT (row.cols == caption.cols)
1382 table_add_row_from_strlist (table, row);
1385 table_rendered = table_render (table);
1387 printf("%ls\n", table_rendered);
1389 printf("%s\n", table_rendered);
1391 ped_free (table_rendered);
1393 table_destroy (table);
1394 ped_disk_destroy (disk);
1399 ped_disk_destroy (disk);
1405 _print_all (int cli)
1407 PedDevice *current_dev = NULL;
1409 ped_device_probe_all();
1411 while ((current_dev = ped_device_get_next(current_dev))) {
1412 do_print (¤t_dev);
1423 do_quit (PedDevice** dev)
1429 static PedPartitionType
1430 _disk_get_part_type_for_sector (PedDisk* disk, PedSector sector)
1432 PedPartition* extended;
1434 extended = ped_disk_extended_partition (disk);
1436 || !ped_geometry_test_sector_inside (&extended->geom, sector))
1439 return PED_PARTITION_LOGICAL;
1442 /* This function checks if "part" contains a file system, and returs
1443 * 0 if either no file system was found, or the user declined to add it.
1444 * 1 if a file system was found, and the user chose to add it.
1445 * -1 if the user chose to cancel the entire search.
1448 _rescue_add_partition (PedPartition* part)
1450 const PedFileSystemType* fs_type;
1451 PedGeometry* probed;
1452 PedExceptionOption ex_opt;
1453 PedConstraint* constraint;
1457 fs_type = ped_file_system_probe (&part->geom);
1460 probed = ped_file_system_probe_specific (fs_type, &part->geom);
1464 if (!ped_geometry_test_inside (&part->geom, probed)) {
1465 ped_geometry_destroy (probed);
1469 constraint = ped_constraint_exact (probed);
1470 if (!ped_disk_set_partition_geom (part->disk, part, constraint,
1471 probed->start, probed->end)) {
1472 ped_constraint_destroy (constraint);
1475 ped_constraint_destroy (constraint);
1477 found_start = ped_unit_format (probed->dev, probed->start);
1478 found_end = ped_unit_format (probed->dev, probed->end);
1479 ex_opt = ped_exception_throw (
1480 PED_EXCEPTION_INFORMATION,
1481 PED_EXCEPTION_YES_NO_CANCEL,
1482 _("A %s %s partition was found at %s -> %s. "
1483 "Do you want to add it to the partition table?"),
1484 fs_type->name, ped_partition_type_get_name (part->type),
1485 found_start, found_end);
1486 ped_geometry_destroy (probed);
1487 ped_free (found_start);
1488 ped_free (found_end);
1491 case PED_EXCEPTION_CANCEL: return -1;
1492 case PED_EXCEPTION_NO: return 0;
1495 ped_partition_set_system (part, fs_type);
1496 ped_disk_commit (part->disk);
1500 /* hack: we only iterate through the start, since most (all) fs's have their
1501 * superblocks at the start. We'll need to change this if we generalize
1502 * for RAID, or something...
1505 _rescue_pass (PedDisk* disk, PedGeometry* start_range, PedGeometry* end_range)
1508 PedGeometry start_geom_exact;
1509 PedGeometry entire_dev;
1510 PedConstraint constraint;
1512 PedPartitionType part_type;
1514 part_type = _disk_get_part_type_for_sector (
1515 disk, (start_range->start + end_range->end) / 2);
1517 ped_geometry_init (&entire_dev, disk->dev, 0, disk->dev->length);
1519 ped_timer_reset (timer);
1520 ped_timer_set_state_name (timer, _("searching for file systems"));
1521 for (start = start_range->start; start <= start_range->end; start++) {
1522 ped_timer_update (timer, 1.0 * (start - start_range->start)
1523 / start_range->length);
1525 ped_geometry_init (&start_geom_exact, disk->dev, start, 1);
1526 ped_constraint_init (
1527 &constraint, ped_alignment_any, ped_alignment_any,
1528 &start_geom_exact, &entire_dev,
1529 1, disk->dev->length);
1530 part = ped_partition_new (disk, part_type, NULL, start,
1533 ped_constraint_done (&constraint);
1537 ped_exception_fetch_all ();
1538 if (ped_disk_add_partition (disk, part, &constraint)) {
1539 ped_exception_leave_all ();
1540 switch (_rescue_add_partition (part)) {
1542 ped_constraint_done (&constraint);
1546 ped_disk_remove_partition (disk, part);
1550 goto error_remove_partition;
1553 ped_exception_leave_all ();
1555 ped_partition_destroy (part);
1556 ped_constraint_done (&constraint);
1558 ped_timer_update (timer, 1.0);
1562 error_remove_partition:
1563 ped_disk_remove_partition (disk, part);
1564 error_partition_destroy:
1565 ped_partition_destroy (part);
1566 error_constraint_done:
1567 ped_constraint_done (&constraint);
1573 do_rescue (PedDevice** dev)
1576 PedSector start = 0, end = 0;
1578 PedGeometry probe_start_region;
1579 PedGeometry probe_end_region;
1581 disk = ped_disk_new (*dev);
1585 if (!command_line_get_sector (_("Start?"), *dev, &start, NULL))
1586 goto error_destroy_disk;
1587 if (!command_line_get_sector (_("End?"), *dev, &end, NULL))
1588 goto error_destroy_disk;
1590 fuzz = PED_MAX (PED_MIN ((end - start) / 10, MEGABYTE_SECTORS(*dev)),
1591 MEGABYTE_SECTORS(*dev) * 16);
1593 ped_geometry_init (&probe_start_region, *dev,
1594 PED_MAX(start - fuzz, 0),
1595 PED_MIN(2 * fuzz, (*dev)->length - (start - fuzz)));
1596 ped_geometry_init (&probe_end_region, *dev,
1597 PED_MAX(end - fuzz, 0),
1598 PED_MIN(2 * fuzz, (*dev)->length - (end - fuzz)));
1600 if (!_rescue_pass (disk, &probe_start_region, &probe_end_region))
1601 goto error_destroy_disk;
1603 ped_disk_destroy (disk);
1607 ped_disk_destroy (disk);
1613 do_resize (PedDevice** dev)
1616 PedPartition *part = NULL;
1618 PedConstraint *constraint;
1619 PedSector start, end;
1620 PedGeometry *range_start = NULL, *range_end = NULL;
1621 PedGeometry new_geom;
1623 disk = ped_disk_new (*dev);
1627 if (!command_line_get_partition (_("Partition number?"), disk, &part))
1628 goto error_destroy_disk;
1629 if (part->type != PED_PARTITION_EXTENDED) {
1630 if (!_partition_warn_busy (part))
1631 goto error_destroy_disk;
1634 start = part->geom.start;
1635 end = part->geom.end;
1636 if (!command_line_get_sector (_("Start?"), *dev, &start, &range_start))
1637 goto error_destroy_disk;
1638 if (!command_line_get_sector (_("End?"), *dev, &end, &range_end))
1639 goto error_destroy_disk;
1641 if (!ped_geometry_init (&new_geom, *dev, start, end - start + 1))
1642 goto error_destroy_disk;
1643 snap_to_boundaries (&new_geom, &part->geom, disk,
1644 range_start, range_end);
1646 if (part->type == PED_PARTITION_EXTENDED) {
1647 constraint = constraint_from_start_end (*dev,
1648 range_start, range_end);
1649 if (!ped_disk_set_partition_geom (disk, part, constraint,
1650 new_geom.start, new_geom.end))
1651 goto error_destroy_constraint;
1652 ped_partition_set_system (part, NULL);
1654 fs = ped_file_system_open (&part->geom);
1656 goto error_destroy_disk;
1657 constraint = constraint_intersect_and_destroy (
1658 ped_file_system_get_resize_constraint (fs),
1659 constraint_from_start_end (
1660 *dev, range_start, range_end));
1661 if (!ped_disk_set_partition_geom (disk, part, constraint,
1662 new_geom.start, new_geom.end))
1663 goto error_close_fs;
1664 if (!ped_file_system_resize (fs, &part->geom, timer))
1665 goto error_close_fs;
1666 /* may have changed... eg fat16 -> fat32 */
1667 ped_partition_set_system (part, fs->type);
1668 ped_file_system_close (fs);
1671 ped_disk_commit (disk);
1672 ped_constraint_destroy (constraint);
1673 ped_disk_destroy (disk);
1674 if (range_start != NULL)
1675 ped_geometry_destroy (range_start);
1676 if (range_end != NULL)
1677 ped_geometry_destroy (range_end);
1681 ped_file_system_close (fs);
1682 error_destroy_constraint:
1683 ped_constraint_destroy (constraint);
1685 ped_disk_destroy (disk);
1687 if (range_start != NULL)
1688 ped_geometry_destroy (range_start);
1689 if (range_end != NULL)
1690 ped_geometry_destroy (range_end);
1695 do_rm (PedDevice** dev)
1698 PedPartition* part = NULL;
1700 disk = ped_disk_new (*dev);
1704 if (!command_line_get_partition (_("Partition number?"), disk, &part))
1705 goto error_destroy_disk;
1706 if (!_partition_warn_busy (part))
1707 goto error_destroy_disk;
1709 ped_disk_delete_partition (disk, part);
1710 ped_disk_commit (disk);
1711 ped_disk_destroy (disk);
1715 ped_disk_destroy (disk);
1721 do_select (PedDevice** dev)
1723 PedDevice* new_dev = *dev;
1725 if (!command_line_get_device (_("New device?"), &new_dev))
1727 if (!ped_device_open (new_dev))
1730 ped_device_close (*dev);
1732 print_using_dev (*dev);
1737 do_set (PedDevice** dev)
1740 PedPartition* part = NULL;
1741 PedPartitionFlag flag;
1744 disk = ped_disk_new (*dev);
1748 if (!command_line_get_partition (_("Partition number?"), disk, &part))
1749 goto error_destroy_disk;
1750 if (!command_line_get_part_flag (_("Flag to Invert?"), part, &flag))
1751 goto error_destroy_disk;
1752 state = (ped_partition_get_flag (part, flag) == 0 ? 1 : 0);
1754 if (!is_toggle_mode) {
1755 if (!command_line_get_state (_("New state?"), &state))
1756 goto error_destroy_disk;
1759 if (!ped_partition_set_flag (part, flag, state))
1760 goto error_destroy_disk;
1761 if (!ped_disk_commit (disk))
1762 goto error_destroy_disk;
1763 ped_disk_destroy (disk);
1767 ped_disk_destroy (disk);
1773 do_toggle (PedDevice **dev)
1778 result = do_set (dev);
1785 do_unit (PedDevice** dev)
1787 PedUnit unit = ped_unit_get_default ();
1788 if (!command_line_get_unit (_("Unit?"), &unit))
1790 ped_unit_set_default (unit);
1808 PedFileSystemType* fs_type;
1809 PedDiskType* disk_type;
1810 PedPartitionFlag part_flag;
1815 list = str_list_create (_(flag_msg_start), NULL);
1816 for (part_flag = ped_partition_flag_next (0); part_flag;
1817 part_flag = ped_partition_flag_next (part_flag)) {
1821 str_list_append (list, ", ");
1822 str_list_append (list,
1823 _(ped_partition_flag_get_name (part_flag)));
1825 str_list_append (list, "\n");
1827 flag_msg = str_list_convert (list);
1828 str_list_destroy (list);
1832 list = str_list_create (_(unit_msg_start), NULL);
1833 for (unit = PED_UNIT_FIRST; unit <= PED_UNIT_LAST; unit++) {
1837 str_list_append (list, ", ");
1838 str_list_append (list, ped_unit_get_name (unit));
1840 str_list_append (list, "\n");
1842 unit_msg = str_list_convert (list);
1843 str_list_destroy (list);
1846 list = str_list_create (_(label_type_msg_start), NULL);
1849 for (disk_type = ped_disk_type_get_next (NULL);
1850 disk_type; disk_type = ped_disk_type_get_next (disk_type)) {
1851 if (disk_type->ops->write == NULL)
1857 str_list_append (list, ", ");
1858 str_list_append (list, disk_type->name);
1860 str_list_append (list, "\n");
1862 label_type_msg = str_list_convert (list);
1863 str_list_destroy (list);
1865 /* mkfs - file system types */
1866 list = str_list_create (_(fs_type_msg_start), NULL);
1869 for (fs_type = ped_file_system_type_get_next (NULL);
1870 fs_type; fs_type = ped_file_system_type_get_next (fs_type)) {
1871 if (fs_type->ops->create == NULL)
1877 str_list_append (list, ", ");
1878 str_list_append (list, fs_type->name);
1880 str_list_append (list, "\n");
1882 mkfs_fs_type_msg = str_list_convert (list);
1883 str_list_destroy (list);
1885 /* mkpart - file system types */
1886 list = str_list_create (_(fs_type_msg_start), NULL);
1889 for (fs_type = ped_file_system_type_get_next (NULL);
1890 fs_type; fs_type = ped_file_system_type_get_next (fs_type)) {
1894 str_list_append (list, ", ");
1895 str_list_append (list, fs_type->name);
1897 str_list_append (list, "\n");
1899 mkpart_fs_type_msg = str_list_convert (list);
1900 str_list_destroy (list);
1902 /* resize - file system types */
1903 list = str_list_create (_(resize_msg_start), NULL);
1906 for (fs_type = ped_file_system_type_get_next (NULL);
1907 fs_type; fs_type = ped_file_system_type_get_next (fs_type)) {
1908 if (fs_type->ops->resize == NULL)
1914 str_list_append (list, ", ");
1915 str_list_append (list, fs_type->name);
1917 str_list_append (list, "\n");
1919 resize_fs_type_msg = str_list_convert (list);
1920 str_list_destroy (list);
1927 free (mkfs_fs_type_msg);
1928 free (mkpart_fs_type_msg);
1929 free (resize_fs_type_msg);
1930 free (label_type_msg);
1936 command_register (commands, command_create (
1937 str_list_create_unique ("check", _("check"), NULL),
1940 _("check NUMBER do a simple check on the file "
1943 str_list_create (_(number_msg), NULL), 1));
1945 command_register (commands, command_create (
1946 str_list_create_unique ("cp", _("cp"), NULL),
1949 _("cp [FROM-DEVICE] FROM-NUMBER TO-NUMBER copy file system to another "
1952 str_list_create (_(number_msg), _(device_msg), NULL), 1));
1954 command_register (commands, command_create (
1955 str_list_create_unique ("help", _("help"), NULL),
1958 _("help [COMMAND] prints general help, or help "
1963 command_register (commands, command_create (
1964 str_list_create_unique ("mklabel", _("mklabel"), "mktable", _("mktable"), NULL),
1967 _("mklabel,mktable LABEL-TYPE create a new disklabel "
1968 "(partition table)"),
1970 str_list_create (label_type_msg, NULL), 1));
1972 command_register (commands, command_create (
1973 str_list_create_unique ("mkfs", _("mkfs"), NULL),
1976 _("mkfs NUMBER FS-TYPE make a FS-TYPE file "
1977 "system on partititon NUMBER"),
1979 str_list_create (_(number_msg), _(mkfs_fs_type_msg), NULL), 1));
1981 command_register (commands, command_create (
1982 str_list_create_unique ("mkpart", _("mkpart"), NULL),
1985 _("mkpart PART-TYPE [FS-TYPE] START END make a partition"),
1987 str_list_create (_(part_type_msg),
1988 _(mkpart_fs_type_msg),
1991 _("mkpart makes a partition without creating a new file system on the "
1992 "partition. FS-TYPE may be specified to set an appropriate partition ID.\n"),
1995 command_register (commands, command_create (
1996 str_list_create_unique ("mkpartfs", _("mkpartfs"), NULL),
1999 _("mkpartfs PART-TYPE FS-TYPE START END make a partition with a "
2002 str_list_create (_(part_type_msg), _(start_end_msg), NULL), 1));
2004 command_register (commands, command_create (
2005 str_list_create_unique ("move", _("move"), NULL),
2008 _("move NUMBER START END move partition NUMBER"),
2010 str_list_create (_(number_msg), _(start_end_msg), NULL), 1));
2012 command_register (commands, command_create (
2013 str_list_create_unique ("name", _("name"), NULL),
2016 _("name NUMBER NAME name partition NUMBER as NAME"),
2018 str_list_create (_(number_msg), _(name_msg), NULL), 1));
2020 command_register (commands, command_create (
2021 str_list_create_unique ("print", _("print"), NULL),
2024 _("print [free|NUMBER|all] display the partition table, "
2025 "a partition, or all devices"),
2028 _("Without arguments, print displays the entire partition table. With 'free'\n"
2029 "argument, information about free space will be displayed otherwise if a\n"
2030 "partition number is given, then more detailed information is displayed\n"
2031 "about that partition. If the 'all' argument is passed instead, partition\n"
2032 "information for all devices will be displayed.\n"),
2035 command_register (commands, command_create (
2036 str_list_create_unique ("quit", _("quit"), NULL),
2039 _("quit exit program"),
2043 command_register (commands, command_create (
2044 str_list_create_unique ("rescue", _("rescue"), NULL),
2047 _("rescue START END rescue a lost partition near "
2050 str_list_create (_(start_end_msg), NULL), 1));
2052 command_register (commands, command_create (
2053 str_list_create_unique ("resize", _("resize"), NULL),
2056 _("resize NUMBER START END resize partition NUMBER and "
2059 str_list_create (_(number_msg),
2061 _(resize_fs_type_msg), NULL), 1));
2063 command_register (commands, command_create (
2064 str_list_create_unique ("rm", _("rm"), NULL),
2067 _("rm NUMBER delete partition NUMBER"),
2069 str_list_create (_(number_msg), NULL), 1));
2071 command_register (commands, command_create (
2072 str_list_create_unique ("select", _("select"), NULL),
2075 _("select DEVICE choose the device to edit"),
2077 str_list_create (_(device_msg), NULL), 1));
2079 command_register (commands, command_create (
2080 str_list_create_unique ("set", _("set"), NULL),
2083 _("set NUMBER FLAG STATE change the FLAG on partition "
2086 str_list_create (_(number_msg), flag_msg, _(state_msg), NULL), 1));
2088 command_register (commands, command_create (
2089 str_list_create_unique ("toggle", _("toggle"), NULL),
2092 _("toggle [NUMBER [FLAG]] toggle the state of FLAG on "
2093 "partition NUMBER"),
2095 str_list_create (_(number_msg), flag_msg, NULL), 1));
2097 command_register (commands, command_create (
2098 str_list_create_unique ("unit", _("unit"), NULL),
2101 _("unit UNIT set the default unit to UNIT"),
2103 str_list_create (unit_msg, NULL), 1));
2105 command_register (commands, command_create (
2106 str_list_create_unique ("version", _("version"), NULL),
2109 _("version displays the current version "
2110 "of GNU Parted and copyright information"),
2113 _("version displays copyright and version information corressponding to this "
2114 "copy of GNU Parted\n"),
2124 for (walk = commands; *walk; walk++) {
2125 command_destroy (*walk);
2133 /* intialize i18n */
2135 setlocale(LC_ALL, "");
2136 bindtextdomain(PACKAGE, LOCALEDIR);
2137 textdomain(PACKAGE);
2138 #endif /* ENABLE_NLS */
2149 _parse_options (int* argc_ptr, char*** argv_ptr)
2155 #ifdef HAVE_GETOPT_H
2156 opt = getopt_long (*argc_ptr, *argv_ptr, "hilsv",
2159 opt = getopt (*argc_ptr, *argv_ptr, "hilsv");
2165 case 'h': help_msg (); break;
2166 case 'i': opt_script_mode = 0; break;
2167 case 'l': _print_all(1); break;
2168 case 's': opt_script_mode = 1; break;
2169 case 'v': _version (); break;
2173 *argc_ptr -= optind;
2174 *argv_ptr += optind;
2182 _choose_device (int* argc_ptr, char*** argv_ptr)
2186 /* specified on comand line? */
2188 dev = ped_device_get ((*argv_ptr) [0]);
2195 ped_device_probe_all ();
2196 dev = ped_device_get_next (NULL);
2198 if (ped_exception_throw (PED_EXCEPTION_ERROR,
2199 PED_EXCEPTION_RETRY_CANCEL,
2200 _("No device found"))
2201 == PED_EXCEPTION_RETRY)
2208 if (!ped_device_open (dev))
2214 _init (int* argc_ptr, char*** argv_ptr)
2218 #ifdef ENABLE_MTRACE
2228 if (!_parse_options (argc_ptr, argv_ptr))
2229 goto error_done_commands;
2232 if (getuid() != 0) {
2233 printf(_("WARNING: You are not superuser. Watch out for "
2238 dev = _choose_device (argc_ptr, argv_ptr);
2240 goto error_done_commands;
2242 timer = ped_timer_new (_timer_handler, &timer_context);
2244 goto error_done_commands;
2245 timer_context.last_update = 0;
2249 error_done_commands:
2259 _done (PedDevice* dev)
2261 if (dev->boot_dirty && dev->type != PED_DEVICE_FILE) {
2262 ped_exception_throw (
2263 PED_EXCEPTION_WARNING,
2265 _("You should reinstall your boot loader before "
2266 "rebooting. Read section 4 of the Parted User "
2267 "documentation for more information."));
2269 if (dev->type != PED_DEVICE_FILE && !opt_script_mode) {
2270 ped_exception_throw (
2271 PED_EXCEPTION_INFORMATION, PED_EXCEPTION_OK,
2272 _("Don't forget to update /etc/fstab, if "
2276 ped_device_close (dev);
2278 ped_timer_destroy (timer);
2285 main (int argc, char** argv)
2290 dev = _init (&argc, &argv);
2294 if (argc || opt_script_mode)
2295 status = non_interactive_mode (&dev, commands, argc, argv);
2297 status = interactive_mode (&dev, commands);