2 parted - a frontend to libparted
3 Copyright (C) 1999-2003, 2005-2008 Free Software Foundation, Inc.
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 #include "configmake.h"
24 #include "version-etc.h"
30 "<http://parted.alioth.debian.org/cgi-bin/trac.cgi/browser/AUTHORS>"
32 /* The official name of this program (e.g., no `g' prefix). */
33 #define PROGRAM_NAME "parted"
35 #define N_(String) String
39 # define _(String) dgettext (PACKAGE, String)
41 # define _(String) (String)
42 #endif /* ENABLE_NLS */
44 #include <parted/parted.h>
45 #include <parted/debug.h>
61 /* minimum amount of free space to leave, or maximum amount to gobble up */
62 #define MIN_FREESPACE (1000 * 2) /* 1000k */
64 static int MEGABYTE_SECTORS (PedDevice* dev)
66 return PED_MEGABYTE_SIZE / dev->sector_size;
69 /* For long options that have no equivalent short option, use a
70 non-character as a pseudo short option, starting with CHAR_MAX + 1. */
73 PRETEND_INPUT_TTY = CHAR_MAX + 1,
79 time_t predicted_time_left;
82 static const struct option const options[] = {
83 /* name, has-arg, string-return-val, char-return-val */
84 {"help", 0, NULL, 'h'},
85 {"list", 0, NULL, 'l'},
86 {"machine", 0, NULL, 'm'},
87 {"script", 0, NULL, 's'},
88 {"version", 0, NULL, 'v'},
89 {"-pretend-input-tty", 0, NULL, PRETEND_INPUT_TTY},
93 static const char *const options_help [][2] = {
94 {"help", N_("displays this help message")},
95 {"list", N_("lists partition layout on all block devices")},
96 {"machine", N_("displays machine parseable output")},
97 {"script", N_("never prompts for user intervention")},
98 {"version", N_("displays the version")},
104 int opt_script_mode = 0;
105 int pretend_input_tty = 0;
106 int opt_machine_mode = 0;
107 int disk_is_modified = 0;
108 int is_toggle_mode = 0;
110 static const char* number_msg = N_(
111 "NUMBER is the partition number used by Linux. On MS-DOS disk labels, the "
112 "primary partitions number from 1 to 4, logical partitions from 5 onwards.\n");
114 static const char* label_type_msg_start = N_("LABEL-TYPE is one of: ");
115 static const char* flag_msg_start = N_("FLAG is one of: ");
116 static const char* unit_msg_start = N_("UNIT is one of: ");
117 static const char* part_type_msg = N_("PART-TYPE is one of: primary, logical, "
119 static const char* fs_type_msg_start = N_("FS-TYPE is one of: ");
120 static const char* start_end_msg = N_("START and END are disk locations, such as "
121 "4GB or 10%. Negative values count from the end of the disk. "
122 "For example, -1s specifies exactly the last sector.\n");
123 static const char* state_msg = N_("STATE is one of: on, off\n");
124 static const char* device_msg = N_("DEVICE is usually /dev/hda or /dev/sda\n");
125 static const char* name_msg = N_("NAME is any word you want\n");
126 static const char* resize_msg_start = N_("The partition must have one of the "
127 "following FS-TYPEs: ");
129 static const char* copyright_msg = N_(
130 "Copyright (C) 1998 - 2006 Free Software Foundation, Inc.\n"
131 "This program is free software, covered by the GNU General Public License.\n"
133 "This program is distributed in the hope that it will be useful,\n"
134 "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
135 "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
136 "GNU General Public License for more details.\n\n");
138 static char* label_type_msg;
139 static char* flag_msg;
140 static char* unit_msg;
142 static char* mkfs_fs_type_msg;
143 static char* mkpart_fs_type_msg;
144 static char* resize_fs_type_msg;
146 static Command* commands [256] = {NULL};
147 static PedTimer* g_timer;
148 static TimerContext timer_context;
150 static int _print_list ();
151 static void _done (PedDevice* dev);
154 _timer_handler (PedTimer* timer, void* context)
156 TimerContext* tcontext = (TimerContext*) context;
159 if (opt_script_mode || !isatty(fileno(stdout)))
162 if (tcontext->last_update != timer->now && timer->now > timer->start) {
163 tcontext->predicted_time_left
164 = timer->predicted_end - timer->now;
165 tcontext->last_update = timer->now;
171 if (draw_this_time) {
174 if (timer->state_name)
175 printf ("%s... ", timer->state_name);
176 printf (_("%0.f%%\t(time left %.2d:%.2d)"),
178 (int) (tcontext->predicted_time_left / 60),
179 (int) (tcontext->predicted_time_left % 60));
186 _partition_warn_busy (PedPartition* part)
190 if (ped_partition_is_busy (part)) {
191 path = ped_partition_get_path (part);
192 ped_exception_throw (
194 PED_EXCEPTION_CANCEL,
195 _("Partition %s is being used. You must unmount it "
196 "before you modify it with Parted."),
205 _disk_warn_busy (PedDisk* disk)
207 if (ped_device_is_busy (disk->dev))
208 return ped_exception_throw (
210 ? PED_EXCEPTION_ERROR
211 : PED_EXCEPTION_WARNING),
212 PED_EXCEPTION_IGNORE_CANCEL,
213 _("Partition(s) on %s are being used."),
214 disk->dev->path) == PED_EXCEPTION_IGNORE;
220 _partition_warn_loss ()
222 return ped_exception_throw (
223 PED_EXCEPTION_WARNING,
224 PED_EXCEPTION_YES_NO,
225 _("The existing file system will be destroyed and "
226 "all data on the partition will be lost. Do "
227 "you want to continue?"),
228 NULL) == PED_EXCEPTION_YES;
232 _disk_warn_loss (PedDisk* disk)
234 return ped_exception_throw (
235 PED_EXCEPTION_WARNING,
236 PED_EXCEPTION_YES_NO,
237 _("The existing disk label on %s will be destroyed "
238 "and all data on this disk will be lost. Do you "
239 "want to continue?"),
240 disk->dev->path) == PED_EXCEPTION_YES;
243 /* This function changes "sector" to "new_sector" if the new value lies
244 * within the required range.
247 snap (PedSector* sector, PedSector new_sector, PedGeometry* range)
249 PED_ASSERT (ped_geometry_test_sector_inside (range, *sector), return 0);
250 if (!ped_geometry_test_sector_inside (range, new_sector))
252 *sector = new_sector;
263 enum { /* Don't change these values */
268 /* Find the prefered way to adjust the sector s inside range.
269 * If a move isn't allowed or is out of range it can't be selected.
270 * what contains SECT_START if the sector to adjust is a start sector
271 * or SECT_END if it's an end one.
272 * The prefered move is to the nearest allowed boundary of the part
273 * partition (if at equal distance: to start if SECT_START or to end
275 * The distance is returned in dist.
278 prefer_snap (PedSector s, int what, PedGeometry* range, EMoves* allow,
279 PedPartition* part, PedSector* dist)
281 PedSector up_dist = -1, down_dist = -1;
285 PED_ASSERT (what == SECT_START || what == SECT_END, return 0);
287 if (!(*allow & (MOVE_UP | MOVE_DOWN))) {
292 if (*allow & MOVE_UP) {
293 new_sect = part->geom.end + 1 + what;
294 if (ped_geometry_test_sector_inside (range, new_sect))
295 up_dist = new_sect - s;
300 if (*allow & MOVE_DOWN) {
301 new_sect = part->geom.start + what;
302 if (ped_geometry_test_sector_inside (range, new_sect))
303 down_dist = s - new_sect;
305 *allow &= ~MOVE_DOWN;
309 if ((*allow & MOVE_UP) && (*allow & MOVE_DOWN)) {
310 if (down_dist < up_dist || (down_dist == up_dist
311 && what == SECT_START) )
313 else if (up_dist < down_dist || (down_dist == up_dist
314 && what == SECT_END) )
317 PED_ASSERT (0, return 0);
318 } else if (*allow & MOVE_UP)
320 else if (*allow & MOVE_DOWN)
323 *dist = ( move == MOVE_DOWN ? down_dist :
324 ( move == MOVE_UP ? up_dist :
329 /* Snaps a partition to nearby partition boundaries. This is useful for
330 * gobbling up small amounts of free space, and also for reinterpreting small
331 * changes to a partition as non-changes (eg: perhaps the user only wanted to
332 * resize the end of a partition).
333 * Note that this isn't the end of the story... this function is
334 * always called before the constraint solver kicks in. So you don't need to
335 * worry too much about inadvertantly creating overlapping partitions, etc.
338 snap_to_boundaries (PedGeometry* new_geom, PedGeometry* old_geom,
340 PedGeometry* start_range, PedGeometry* end_range)
342 PedPartition* start_part;
343 PedPartition* end_part;
344 PedSector start = new_geom->start;
345 PedSector end = new_geom->end;
346 PedSector start_dist = -1, end_dist = -1;
347 EMoves start_allow, end_allow, start_want, end_want;
350 start_want = end_want = MOVE_NO;
351 start_allow = end_allow = MOVE_STILL | MOVE_UP | MOVE_DOWN;
353 start_part = ped_disk_get_partition_by_sector (disk, start);
354 end_part = ped_disk_get_partition_by_sector (disk, end);
355 adjacent = (start_part->geom.end + 1 == end_part->geom.start);
357 /* If we can snap to old_geom, then we will... */
358 /* and this will enforce the snapped positions */
360 if (snap (&start, old_geom->start, start_range))
361 start_allow = MOVE_STILL;
362 if (snap (&end, old_geom->end, end_range))
363 end_allow = MOVE_STILL;
366 /* If start and end are on the same partition, we */
367 /* don't allow them to cross. */
368 if (start_part == end_part) {
369 start_allow &= ~MOVE_UP;
370 end_allow &= ~MOVE_DOWN;
373 /* Let's find our way */
374 start_want = prefer_snap (start, SECT_START, start_range, &start_allow,
375 start_part, &start_dist );
376 end_want = prefer_snap (end, SECT_END, end_range, &end_allow,
377 end_part, &end_dist );
379 PED_ASSERT (start_dist >= 0 && end_dist >= 0, return);
381 /* If start and end are on adjacent partitions, */
382 /* and if they would prefer crossing, then refrain */
383 /* the farthest to do so. */
384 if (adjacent && start_want == MOVE_UP && end_want == MOVE_DOWN) {
385 if (end_dist < start_dist) {
386 start_allow &= ~MOVE_UP;
387 start_want = prefer_snap (start, SECT_START,
388 start_range, &start_allow,
389 start_part, &start_dist );
390 PED_ASSERT (start_dist >= 0, return);
392 end_allow &= ~MOVE_DOWN;
393 end_want = prefer_snap (end, SECT_END,
394 end_range, &end_allow,
395 end_part, &end_dist );
396 PED_ASSERT (end_dist >= 0, return);
401 start = ( start_want == MOVE_DOWN ? start_part->geom.start :
402 ( start_want == MOVE_UP ? start_part->geom.end + 1 :
404 end = ( end_want == MOVE_DOWN ? end_part->geom.start - 1 :
405 ( end_want == MOVE_UP ? end_part->geom.end :
407 PED_ASSERT (ped_geometry_test_sector_inside(start_range,start), return);
408 PED_ASSERT (ped_geometry_test_sector_inside (end_range, end), return);
409 PED_ASSERT (start <= end,
410 PED_DEBUG (0, "start = %d, end = %d\n", start, end));
411 ped_geometry_set (new_geom, start, end - start + 1);
414 /* This functions constructs a constraint from the following information:
415 * start, is_start_exact, end, is_end_exact.
417 * If is_start_exact == 1, then the constraint requires start be as given in
418 * "start". Otherwise, the constraint does not set any requirements on the
421 static PedConstraint*
422 constraint_from_start_end (PedDevice* dev, PedGeometry* range_start,
423 PedGeometry* range_end)
425 return ped_constraint_new (ped_alignment_any, ped_alignment_any,
426 range_start, range_end, 1, dev->length);
429 static PedConstraint*
430 constraint_intersect_and_destroy (PedConstraint* a, PedConstraint* b)
432 PedConstraint* result = ped_constraint_intersect (a, b);
433 ped_constraint_destroy (a);
434 ped_constraint_destroy (b);
439 help_on (char* topic)
443 cmd = command_get (commands, topic);
446 command_print_help (cmd);
450 do_check (PedDevice** dev)
454 PedPartition* part = NULL;
456 disk = ped_disk_new (*dev);
460 if (!command_line_get_partition (_("Partition number?"), disk, &part))
461 goto error_destroy_disk;
462 if (!_partition_warn_busy (part))
463 goto error_destroy_disk;
465 if (!ped_disk_check (disk))
466 goto error_destroy_disk;
468 fs = ped_file_system_open (&part->geom);
470 goto error_destroy_disk;
471 if (!ped_file_system_check (fs, g_timer))
473 ped_file_system_close (fs);
474 ped_disk_destroy (disk);
478 ped_file_system_close (fs);
480 ped_disk_destroy (disk);
486 do_cp (PedDevice** dev)
490 PedPartition* src = NULL;
491 PedPartition* dst = NULL;
492 PedFileSystem* src_fs;
493 PedFileSystem* dst_fs;
494 PedFileSystemType* dst_fs_type;
496 dst_disk = ped_disk_new (*dev);
501 if (!command_line_is_integer ()) {
502 if (!command_line_get_disk (_("Source device?"), &src_disk))
503 goto error_destroy_disk;
506 if (!command_line_get_partition (_("Source partition number?"),
508 goto error_destroy_disk;
509 if (src->type == PED_PARTITION_EXTENDED) {
510 ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
511 _("Can't copy an extended partition."));
512 goto error_destroy_disk;
514 if (!_partition_warn_busy (src))
515 goto error_destroy_disk;
517 if (!command_line_get_partition (_("Destination partition number?"),
519 goto error_destroy_disk;
520 if (!_partition_warn_busy (dst))
521 goto error_destroy_disk;
524 src_fs = ped_file_system_open (&src->geom);
526 goto error_destroy_disk;
527 dst_fs = ped_file_system_copy (src_fs, &dst->geom, g_timer);
529 goto error_close_src_fs;
530 dst_fs_type = dst_fs->type; /* may be different to src_fs->type */
531 ped_file_system_close (src_fs);
532 ped_file_system_close (dst_fs);
534 /* update the partition table, close disks */
535 if (!ped_partition_set_system (dst, dst_fs_type))
536 goto error_destroy_disk;
537 if (!ped_disk_commit (dst_disk))
538 goto error_destroy_disk;
539 if (src_disk != dst_disk)
540 ped_disk_destroy (src_disk);
541 ped_disk_destroy (dst_disk);
543 if ((*dev)->type != PED_DEVICE_FILE)
544 disk_is_modified = 1;
549 ped_file_system_close (src_fs);
551 if (src_disk && src_disk != dst_disk)
552 ped_disk_destroy (src_disk);
553 ped_disk_destroy (dst_disk);
559 print_commands_help ()
563 for (i=0; commands [i]; i++)
564 command_print_summary (commands [i]);
568 print_options_help ()
572 for (i=0; options_help [i][0]; i++) {
573 printf (" -%c, --%-23.23s %s\n",
574 options_help [i][0][0],
576 _(options_help [i][1]));
581 do_help (PedDevice** dev)
583 if (command_line_get_word_count ()) {
584 char* word = command_line_pop_word ();
590 print_commands_help();
596 do_mklabel (PedDevice** dev)
599 const PedDiskType* type = ped_disk_probe (*dev);
601 ped_exception_fetch_all ();
602 disk = ped_disk_new (*dev);
603 if (!disk) ped_exception_catch ();
604 ped_exception_leave_all ();
607 if (!_disk_warn_busy (disk))
608 goto error_destroy_disk;
609 if (!opt_script_mode && !_disk_warn_loss (disk))
610 goto error_destroy_disk;
612 ped_disk_destroy (disk);
615 if (!command_line_get_disk_type (_("New disk label type?"), &type))
618 disk = ped_disk_new_fresh (*dev, type);
622 if (!ped_disk_commit (disk))
623 goto error_destroy_disk;
624 ped_disk_destroy (disk);
626 if ((*dev)->type != PED_DEVICE_FILE)
627 disk_is_modified = 1;
632 ped_disk_destroy (disk);
638 do_mkfs (PedDevice** dev)
641 PedPartition* part = NULL;
642 const PedFileSystemType* type = ped_file_system_type_get ("ext2");
645 disk = ped_disk_new (*dev);
649 if (!opt_script_mode && !_partition_warn_loss())
650 goto error_destroy_disk;
652 if (!command_line_get_partition (_("Partition number?"), disk, &part))
653 goto error_destroy_disk;
654 if (!_partition_warn_busy (part))
655 goto error_destroy_disk;
656 if (!command_line_get_fs_type (_("File system type?"), &type))
657 goto error_destroy_disk;
659 fs = ped_file_system_create (&part->geom, type, g_timer);
661 goto error_destroy_disk;
662 ped_file_system_close (fs);
664 if (!ped_partition_set_system (part, type))
665 goto error_destroy_disk;
666 if (ped_partition_is_flag_available (part, PED_PARTITION_LBA))
667 ped_partition_set_flag (part, PED_PARTITION_LBA, 1);
668 if (!ped_disk_commit (disk))
669 goto error_destroy_disk;
670 ped_disk_destroy (disk);
672 if ((*dev)->type != PED_DEVICE_FILE)
673 disk_is_modified = 1;
678 ped_disk_destroy (disk);
684 do_mkpart (PedDevice** dev)
688 PedPartitionType part_type;
689 const PedFileSystemType* fs_type = ped_file_system_type_get ("ext2");
690 PedSector start = 0, end = 0;
691 PedGeometry *range_start = NULL, *range_end = NULL;
692 PedConstraint* user_constraint;
693 PedConstraint* dev_constraint;
694 PedConstraint* final_constraint;
696 char* part_name = NULL;
697 char *start_usr = NULL, *end_usr = NULL;
698 char *start_sol = NULL, *end_sol = NULL;
700 disk = ped_disk_new (*dev);
704 if (!ped_disk_type_check_feature (disk->type, PED_DISK_TYPE_EXTENDED)) {
705 part_type = PED_PARTITION_NORMAL;
707 if (!command_line_get_part_type (_("Partition type?"),
709 goto error_destroy_disk;
712 /* The undocumented feature that mkpart sometimes takes a
713 partition name is next to useless, at least with a dvh
714 partition table, since it makes the "mkpart" command
715 fail unconditionally for a primary partition. E.g.,
716 mkpart primary any-name xfs 4096s 5000s
717 requires the name, yet always fails, saying that only
718 logical partitions may have names.
719 If you want a name, use parted's separate "name" command. */
721 if (ped_disk_type_check_feature (disk->type,
722 PED_DISK_TYPE_PARTITION_NAME)
723 && ! (strcmp (disk->type->name, "dvh") == 0
724 && part_type != PED_PARTITION_LOGICAL))
725 part_name = command_line_get_word (_("Partition name?"),
728 peek_word = command_line_peek_word ();
729 if (part_type == PED_PARTITION_EXTENDED
730 || (peek_word && isdigit (peek_word[0]))) {
733 if (!command_line_get_fs_type (_("File system type?"),
735 goto error_destroy_disk;
739 if (!command_line_get_sector (_("Start?"), *dev, &start, &range_start))
740 goto error_destroy_disk;
741 if (!command_line_get_sector (_("End?"), *dev, &end, &range_end))
742 goto error_destroy_disk;
744 /* processing starts here */
745 part = ped_partition_new (disk, part_type, fs_type, start, end);
747 goto error_destroy_disk;
749 snap_to_boundaries (&part->geom, NULL, disk, range_start, range_end);
751 /* create constraints */
752 user_constraint = constraint_from_start_end (*dev, range_start,
754 PED_ASSERT (user_constraint != NULL, return 0);
756 dev_constraint = ped_device_get_constraint (*dev);
757 PED_ASSERT (dev_constraint != NULL, return 0);
759 final_constraint = ped_constraint_intersect (user_constraint,
761 ped_constraint_destroy (user_constraint);
762 ped_constraint_destroy (dev_constraint);
763 if (!final_constraint)
764 goto error_destroy_simple_constraints;
766 /* subject to partition constraint */
767 ped_exception_fetch_all();
768 bool added_ok = ped_disk_add_partition (disk, part, final_constraint);
769 ped_constraint_destroy (final_constraint);
771 ped_exception_leave_all();
773 if (ped_disk_add_partition (disk, part,
774 ped_constraint_any (*dev))) {
775 start_usr = ped_unit_format (*dev, start);
776 end_usr = ped_unit_format (*dev, end);
777 start_sol = ped_unit_format (*dev, part->geom.start);
778 end_sol = ped_unit_format (*dev, part->geom.end);
780 switch (ped_exception_throw (
781 PED_EXCEPTION_WARNING,
782 PED_EXCEPTION_YES_NO,
783 _("You requested a partition from %s to %s.\n"
784 "The closest location we can manage is "
786 "Is this still acceptable to you?"),
787 start_usr, end_usr, start_sol, end_sol))
789 case PED_EXCEPTION_YES:
790 /* all is well in this state */
792 case PED_EXCEPTION_NO:
793 case PED_EXCEPTION_UNHANDLED:
795 /* undo partition addition */
796 goto error_remove_part;
799 goto error_remove_part;
802 ped_exception_leave_all();
804 ped_exception_catch();
806 /* set minor attributes */
808 PED_ASSERT (ped_partition_set_name (part, part_name), return 0);
809 if (!ped_partition_set_system (part, fs_type))
810 goto error_destroy_disk;
811 if (ped_partition_is_flag_available (part, PED_PARTITION_LBA))
812 ped_partition_set_flag (part, PED_PARTITION_LBA, 1);
814 if (!ped_disk_commit (disk))
815 goto error_destroy_disk;
818 ped_disk_destroy (disk);
820 if (range_start != NULL)
821 ped_geometry_destroy (range_start);
822 if (range_end != NULL)
823 ped_geometry_destroy (range_end);
830 if ((*dev)->type != PED_DEVICE_FILE)
831 disk_is_modified = 1;
836 ped_disk_remove_partition (disk, part);
837 error_destroy_simple_constraints:
838 ped_partition_destroy (part);
840 ped_disk_destroy (disk);
842 if (range_start != NULL)
843 ped_geometry_destroy (range_start);
844 if (range_end != NULL)
845 ped_geometry_destroy (range_end);
856 do_mkpartfs (PedDevice** dev)
860 PedPartitionType part_type;
861 const PedFileSystemType* fs_type = ped_file_system_type_get ("ext2");
862 PedSector start = 0, end = 0;
863 PedGeometry *range_start = NULL, *range_end = NULL;
864 PedConstraint* user_constraint;
865 PedConstraint* dev_constraint;
866 PedConstraint* final_constraint;
868 char* part_name = NULL;
869 char *start_usr = NULL, *end_usr = NULL;
870 char *start_sol = NULL, *end_sol = NULL;
872 disk = ped_disk_new (*dev);
876 if (!ped_disk_type_check_feature (disk->type, PED_DISK_TYPE_EXTENDED)) {
877 part_type = PED_PARTITION_NORMAL;
879 if (!command_line_get_part_type (_("Partition type?"),
881 goto error_destroy_disk;
884 if (ped_disk_type_check_feature (disk->type,
885 PED_DISK_TYPE_PARTITION_NAME))
886 part_name = command_line_get_word (_("Partition name?"),
889 if (part_type == PED_PARTITION_EXTENDED) {
890 ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
891 _("An extended partition cannot hold a file system. "
892 "Did you want mkpart?"));
893 goto error_destroy_disk;
896 if (!command_line_get_fs_type (_("File system type?"), &fs_type))
897 goto error_destroy_disk;
898 if (!command_line_get_sector (_("Start?"), *dev, &start,
900 goto error_destroy_disk;
901 if (!command_line_get_sector (_("End?"), *dev, &end, &range_end))
902 goto error_destroy_disk;
904 /* attempt to create the partition now */
905 part = ped_partition_new (disk, part_type, fs_type, start, end);
907 goto error_destroy_disk;
909 snap_to_boundaries (&part->geom, NULL, disk, range_start, range_end);
911 /* create constraints */
912 user_constraint = constraint_from_start_end (*dev, range_start,
914 PED_ASSERT (user_constraint != NULL, return 0);
916 dev_constraint = ped_device_get_constraint (*dev);
917 PED_ASSERT (dev_constraint != NULL, return 0);
919 final_constraint = ped_constraint_intersect (user_constraint,
921 ped_constraint_destroy (user_constraint);
922 ped_constraint_destroy (dev_constraint);
923 if (!final_constraint)
924 goto error_destroy_simple_constraints;
926 /* subject to partition constraint */
927 ped_exception_fetch_all();
928 bool added_ok = ped_disk_add_partition (disk, part, final_constraint);
929 ped_constraint_destroy (final_constraint);
931 ped_exception_leave_all();
933 if (ped_disk_add_partition (disk, part,
934 ped_constraint_any (*dev))) {
935 start_usr = ped_unit_format (*dev, start);
936 end_usr = ped_unit_format (*dev, end);
937 start_sol = ped_unit_format (*dev, part->geom.start);
938 end_sol = ped_unit_format (*dev, part->geom.end);
940 switch (ped_exception_throw (
941 PED_EXCEPTION_WARNING,
942 PED_EXCEPTION_YES_NO,
943 _("You requested a partition from %s to %s.\n"
944 "The closest location we can manage is "
946 "Is this still acceptable to you?"),
947 start_usr, end_usr, start_sol, end_sol)) {
948 case PED_EXCEPTION_YES:
949 /* all is well in this state */
951 case PED_EXCEPTION_NO:
952 case PED_EXCEPTION_UNHANDLED:
954 /* undo partition addition */
955 goto error_remove_part;
958 goto error_remove_part;
961 ped_exception_leave_all();
963 ped_exception_catch();
965 /* set LBA flag automatically if available */
966 if (ped_partition_is_flag_available (part, PED_PARTITION_LBA))
967 ped_partition_set_flag (part, PED_PARTITION_LBA, 1);
970 fs = ped_file_system_create (&part->geom, fs_type, g_timer);
972 goto error_destroy_disk;
973 ped_file_system_close (fs);
975 if (!ped_partition_set_system (part, fs_type))
976 goto error_destroy_disk;
978 if (!ped_disk_commit (disk))
979 goto error_destroy_disk;
983 ped_disk_destroy (disk);
985 if (range_start != NULL)
986 ped_geometry_destroy (range_start);
987 if (range_end != NULL)
988 ped_geometry_destroy (range_end);
995 if ((*dev)->type != PED_DEVICE_FILE)
996 disk_is_modified = 1;
1001 ped_disk_remove_partition (disk, part);
1002 error_destroy_simple_constraints:
1003 ped_partition_destroy (part);
1005 ped_disk_destroy (disk);
1007 if (range_start != NULL)
1008 ped_geometry_destroy (range_start);
1009 if (range_end != NULL)
1010 ped_geometry_destroy (range_end);
1021 do_move (PedDevice** dev)
1024 PedPartition* part = NULL;
1026 PedFileSystem* fs_copy;
1027 PedConstraint* constraint;
1028 PedSector start = 0, end = 0;
1029 PedGeometry *range_start = NULL, *range_end = NULL;
1030 PedGeometry old_geom, new_geom;
1032 disk = ped_disk_new (*dev);
1036 if (!command_line_get_partition (_("Partition number?"), disk, &part))
1037 goto error_destroy_disk;
1038 if (!_partition_warn_busy (part))
1039 goto error_destroy_disk;
1040 if (part->type == PED_PARTITION_EXTENDED) {
1041 ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
1042 _("Can't move an extended partition."));
1043 goto error_destroy_disk;
1045 old_geom = part->geom;
1046 fs = ped_file_system_open (&old_geom);
1048 goto error_destroy_disk;
1050 /* get new target */
1051 if (!command_line_get_sector (_("Start?"), *dev, &start, &range_start))
1052 goto error_close_fs;
1053 end = start + old_geom.length - 1;
1054 if (!command_line_get_sector (_("End?"), *dev, &end, &range_end))
1055 goto error_close_fs;
1057 /* set / test on "disk" */
1058 if (!ped_geometry_init (&new_geom, *dev, start, end - start + 1))
1059 goto error_close_fs;
1060 snap_to_boundaries (&new_geom, NULL, disk, range_start, range_end);
1062 constraint = constraint_intersect_and_destroy (
1063 ped_file_system_get_copy_constraint (fs, *dev),
1064 constraint_from_start_end(*dev,range_start,range_end));
1065 if (!ped_disk_set_partition_geom (disk, part, constraint,
1066 new_geom.start, new_geom.end))
1067 goto error_destroy_constraint;
1068 ped_constraint_destroy (constraint);
1069 if (ped_geometry_test_overlap (&old_geom, &part->geom)) {
1070 ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
1071 _("Can't move a partition onto itself. Try using "
1072 "resize, perhaps?"));
1073 goto error_close_fs;
1077 fs_copy = ped_file_system_copy (fs, &part->geom, g_timer);
1079 goto error_close_fs;
1080 ped_file_system_close (fs_copy);
1081 ped_file_system_close (fs);
1082 if (!ped_disk_commit (disk))
1083 goto error_destroy_disk;
1084 ped_disk_destroy (disk);
1085 if (range_start != NULL)
1086 ped_geometry_destroy (range_start);
1087 if (range_end != NULL)
1088 ped_geometry_destroy (range_end);
1090 if ((*dev)->type != PED_DEVICE_FILE)
1091 disk_is_modified = 1;
1095 error_destroy_constraint:
1096 ped_constraint_destroy (constraint);
1098 ped_file_system_close (fs);
1100 ped_disk_destroy (disk);
1102 if (range_start != NULL)
1103 ped_geometry_destroy (range_start);
1104 if (range_end != NULL)
1105 ped_geometry_destroy (range_end);
1110 do_name (PedDevice** dev)
1113 PedPartition* part = NULL;
1116 disk = ped_disk_new (*dev);
1120 if (!command_line_get_partition (_("Partition number?"), disk, &part))
1121 goto error_destroy_disk;
1123 name = command_line_get_word (_("Partition name?"),
1124 ped_partition_get_name (part), NULL, 0);
1126 goto error_destroy_disk;
1127 if (!ped_partition_set_name (part, name))
1128 goto error_free_name;
1131 if (!ped_disk_commit (disk))
1132 goto error_destroy_disk;
1133 ped_disk_destroy (disk);
1139 ped_disk_destroy (disk);
1145 partition_print_flags (PedPartition* part)
1147 PedPartitionFlag flag;
1150 char* res = ped_malloc(1);
1156 for (flag = ped_partition_flag_next (0); flag;
1157 flag = ped_partition_flag_next (flag)) {
1158 if (ped_partition_get_flag (part, flag)) {
1163 ped_realloc (&_res, strlen (res)
1166 strncat (res, ", ", 2);
1169 name = _(ped_partition_flag_get_name (flag));
1171 ped_realloc (&_res, strlen (res) + 1
1174 strncat (res, name, 21);
1181 /* Prints a sector out, first in compact form, and then with a percentage.
1185 print_sector_compact_and_percent (PedSector sector, PedDevice* dev)
1190 if (ped_unit_get_default() == PED_UNIT_PERCENT)
1191 compact = ped_unit_format (dev, sector);
1193 compact = ped_unit_format_custom (dev, sector,
1196 percent = ped_unit_format_custom (dev, sector, PED_UNIT_PERCENT);
1198 printf ("%s (%s)\n", compact, percent);
1205 partition_print (PedPartition* part)
1208 PedConstraint* resize_constraint;
1211 fs = ped_file_system_open (&part->geom);
1217 flags = partition_print_flags (part);
1219 printf (_("Minor: %d\n"), part->num);
1220 printf (_("Flags: %s\n"), flags);
1221 printf (_("File System: %s\n"), fs->type->name);
1222 fputs (_("Size: "), stdout);
1223 print_sector_compact_and_percent (part->geom.length, part->geom.dev);
1225 resize_constraint = ped_file_system_get_resize_constraint (fs);
1226 if (resize_constraint) {
1227 fputs (_("Minimum size: "), stdout);
1228 print_sector_compact_and_percent (resize_constraint->min_size,
1230 fputs (_("Maximum size: "), stdout);
1231 print_sector_compact_and_percent (resize_constraint->max_size,
1233 ped_constraint_destroy (resize_constraint);
1239 ped_file_system_close (fs);
1245 do_print (PedDevice** dev)
1247 PedUnit default_unit;
1252 int has_devices_arg = 0;
1253 int has_free_arg = 0;
1254 int has_list_arg = 0;
1255 int has_num_arg = 0;
1256 const char *const transport[14] = {"unknown", "scsi", "ide", "dac960",
1257 "cpqarray", "file", "ataraid", "i2o",
1258 "ubd", "dasd", "viodasd", "sx8", "dm",
1267 wchar_t* table_rendered;
1269 disk = ped_disk_new (*dev);
1273 peek_word = command_line_peek_word ();
1275 if (strncmp (peek_word, "devices", 7) == 0) {
1276 command_line_pop_word();
1277 has_devices_arg = 1;
1279 else if (strncmp (peek_word, "free", 4) == 0) {
1280 command_line_pop_word ();
1283 else if (strncmp (peek_word, "list", 4) == 0 ||
1284 strncmp (peek_word, "all", 3) == 0) {
1285 command_line_pop_word();
1289 has_num_arg = isdigit(peek_word[0]);
1294 if (has_devices_arg) {
1296 PedDevice* current_dev = NULL;
1298 ped_device_probe_all();
1300 while ((current_dev = ped_device_get_next(current_dev))) {
1301 end = ped_unit_format_byte (current_dev,
1303 * current_dev->sector_size);
1304 printf ("%s (%s)\n", current_dev->path, end);
1308 dev_name = xstrdup ((*dev)->path);
1309 ped_device_free_all ();
1311 *dev = ped_device_get (dev_name);
1314 if (!ped_device_open (*dev))
1322 else if (has_list_arg)
1323 return _print_list ();
1325 else if (has_num_arg) {
1326 PedPartition* part = NULL;
1328 if (command_line_get_partition ("", disk, &part))
1329 status = partition_print (part);
1330 ped_disk_destroy (disk);
1334 start = ped_unit_format (*dev, 0);
1335 default_unit = ped_unit_get_default ();
1336 end = ped_unit_format_byte (*dev, (*dev)->length * (*dev)->sector_size
1337 - (default_unit == PED_UNIT_CHS ||
1338 default_unit == PED_UNIT_CYLINDER));
1340 if (opt_machine_mode) {
1341 switch (default_unit) {
1342 case PED_UNIT_CHS: puts ("CHS;");
1344 case PED_UNIT_CYLINDER: puts ("CYL;");
1346 default: puts ("BYT;");
1350 printf ("%s:%s:%s:%lld:%lld:%s:%s;\n",
1351 (*dev)->path, end, transport[(*dev)->type],
1352 (*dev)->sector_size, (*dev)->phys_sector_size,
1353 disk->type->name, (*dev)->model);
1355 printf (_("Model: %s (%s)\n"),
1356 (*dev)->model, transport[(*dev)->type]);
1357 printf (_("Disk %s: %s\n"), (*dev)->path, end);
1358 printf (_("Sector size (logical/physical): %lldB/%lldB\n"),
1359 (*dev)->sector_size, (*dev)->phys_sector_size);
1365 if (ped_unit_get_default () == PED_UNIT_CHS
1366 || ped_unit_get_default () == PED_UNIT_CYLINDER) {
1367 PedCHSGeometry* chs = &(*dev)->bios_geom;
1368 char* cyl_size = ped_unit_format_custom (*dev,
1369 chs->heads * chs->sectors,
1372 if (opt_machine_mode) {
1373 printf ("%d:%d:%d:%s;\n",
1374 chs->cylinders, chs->heads, chs->sectors, cyl_size);
1376 printf (_("BIOS cylinder,head,sector geometry: %d,%d,%d. "
1377 "Each cylinder is %s.\n"),
1378 chs->cylinders, chs->heads, chs->sectors, cyl_size);
1384 if (!opt_machine_mode) {
1385 printf (_("Partition Table: %s\n"), disk->type->name);
1389 has_extended = ped_disk_type_check_feature (disk->type,
1390 PED_DISK_TYPE_EXTENDED);
1391 has_name = ped_disk_type_check_feature (disk->type,
1392 PED_DISK_TYPE_PARTITION_NAME);
1396 if (!opt_machine_mode) {
1399 if (ped_unit_get_default() == PED_UNIT_CHS) {
1400 row1 = str_list_create (_("Number"), _("Start"),
1403 row1 = str_list_create (_("Number"), _("Start"),
1404 _("End"), _("Size"), NULL);
1408 str_list_append (row1, _("Type"));
1410 str_list_append (row1, _("File system"));
1413 str_list_append (row1, _("Name"));
1415 str_list_append (row1, _("Flags"));
1418 table = table_new (str_list_length(row1));
1420 table_add_row_from_strlist (table, row1);
1422 for (part = ped_disk_next_partition (disk, NULL); part;
1423 part = ped_disk_next_partition (disk, part)) {
1425 if ((!has_free_arg && !ped_partition_is_active(part)) ||
1426 part->type & PED_PARTITION_METADATA)
1429 tmp = ped_malloc (4);
1432 sprintf (tmp, "%2d ", part->num);
1434 sprintf (tmp, "%2s ", "");
1436 StrList *row = str_list_create (tmp, NULL);
1438 start = ped_unit_format (*dev, part->geom.start);
1439 end = ped_unit_format_byte (
1441 (part->geom.end + 1) * (*dev)->sector_size - 1);
1442 size = ped_unit_format (*dev, part->geom.length);
1443 if (ped_unit_get_default() == PED_UNIT_CHS) {
1444 str_list_append (row, start);
1445 str_list_append (row, end);
1447 str_list_append (row, start);
1448 str_list_append (row, end);
1449 str_list_append (row, size);
1452 if (!(part->type & PED_PARTITION_FREESPACE)) {
1454 name = ped_partition_type_get_name (part->type);
1455 str_list_append (row, name);
1458 str_list_append (row, part->fs_type ?
1459 part->fs_type->name : "");
1462 name = ped_partition_get_name (part);
1463 str_list_append (row, name);
1466 flags = partition_print_flags (part);
1467 str_list_append (row, flags);
1471 str_list_append (row, "");
1472 str_list_append (row, _("Free Space"));
1474 str_list_append (row, "");
1475 str_list_append (row, "");
1478 //PED_ASSERT (row.cols == caption.cols)
1479 table_add_row_from_strlist (table, row);
1480 str_list_destroy (row);
1487 table_rendered = table_render (table);
1489 printf("%ls\n", table_rendered);
1491 printf("%s\n", table_rendered);
1493 free (table_rendered);
1494 table_destroy (table);
1495 str_list_destroy (row1);
1499 for (part = ped_disk_next_partition (disk, NULL); part;
1500 part = ped_disk_next_partition (disk, part)) {
1502 if ((!has_free_arg && !ped_partition_is_active(part)) ||
1503 part->type & PED_PARTITION_METADATA)
1507 printf ("%d:", part->num);
1509 fputs ("1:", stdout);
1511 char *s = ped_unit_format (*dev, part->geom.start);
1514 s = ped_unit_format_byte (*dev,
1515 (part->geom.end + 1) *
1516 (*dev)->sector_size - 1);
1520 if (ped_unit_get_default() != PED_UNIT_CHS) {
1521 s = ped_unit_format (*dev, part->geom.length);
1526 if (!(part->type & PED_PARTITION_FREESPACE)) {
1529 printf ("%s:", part->fs_type->name);
1534 printf ("%s:", _(ped_partition_get_name (part)));
1538 printf ("%s;\n", partition_print_flags (part));
1546 ped_disk_destroy (disk);
1550 ped_disk_destroy (disk);
1558 PedDevice *current_dev = NULL;
1560 ped_device_probe_all();
1562 while ((current_dev = ped_device_get_next(current_dev))) {
1563 do_print (¤t_dev);
1571 do_quit (PedDevice** dev)
1577 static PedPartitionType
1578 _disk_get_part_type_for_sector (PedDisk* disk, PedSector sector)
1580 PedPartition* extended;
1582 extended = ped_disk_extended_partition (disk);
1584 || !ped_geometry_test_sector_inside (&extended->geom, sector))
1587 return PED_PARTITION_LOGICAL;
1590 /* This function checks if "part" contains a file system, and returs
1591 * 0 if either no file system was found, or the user declined to add it.
1592 * 1 if a file system was found, and the user chose to add it.
1593 * -1 if the user chose to cancel the entire search.
1596 _rescue_add_partition (PedPartition* part)
1598 const PedFileSystemType* fs_type;
1599 PedGeometry* probed;
1600 PedExceptionOption ex_opt;
1601 PedConstraint* constraint;
1605 fs_type = ped_file_system_probe (&part->geom);
1608 probed = ped_file_system_probe_specific (fs_type, &part->geom);
1612 if (!ped_geometry_test_inside (&part->geom, probed)) {
1613 ped_geometry_destroy (probed);
1617 constraint = ped_constraint_exact (probed);
1618 if (!ped_disk_set_partition_geom (part->disk, part, constraint,
1619 probed->start, probed->end)) {
1620 ped_constraint_destroy (constraint);
1623 ped_constraint_destroy (constraint);
1625 found_start = ped_unit_format (probed->dev, probed->start);
1626 found_end = ped_unit_format (probed->dev, probed->end);
1627 ex_opt = ped_exception_throw (
1628 PED_EXCEPTION_INFORMATION,
1629 PED_EXCEPTION_YES_NO_CANCEL,
1630 _("A %s %s partition was found at %s -> %s. "
1631 "Do you want to add it to the partition table?"),
1632 fs_type->name, ped_partition_type_get_name (part->type),
1633 found_start, found_end);
1634 ped_geometry_destroy (probed);
1639 case PED_EXCEPTION_CANCEL: return -1;
1640 case PED_EXCEPTION_NO: return 0;
1644 ped_partition_set_system (part, fs_type);
1645 ped_disk_commit (part->disk);
1649 /* hack: we only iterate through the start, since most (all) fs's have their
1650 * superblocks at the start. We'll need to change this if we generalize
1651 * for RAID, or something...
1654 _rescue_pass (PedDisk* disk, PedGeometry* start_range, PedGeometry* end_range)
1657 PedGeometry start_geom_exact;
1658 PedGeometry entire_dev;
1659 PedConstraint constraint;
1661 PedPartitionType part_type;
1663 part_type = _disk_get_part_type_for_sector (
1664 disk, (start_range->start + end_range->end) / 2);
1666 ped_geometry_init (&entire_dev, disk->dev, 0, disk->dev->length);
1668 ped_timer_reset (g_timer);
1669 ped_timer_set_state_name (g_timer, _("searching for file systems"));
1670 for (start = start_range->start; start <= start_range->end; start++) {
1671 ped_timer_update (g_timer, 1.0 * (start - start_range->start)
1672 / start_range->length);
1674 ped_geometry_init (&start_geom_exact, disk->dev, start, 1);
1675 ped_constraint_init (
1676 &constraint, ped_alignment_any, ped_alignment_any,
1677 &start_geom_exact, &entire_dev,
1678 1, disk->dev->length);
1679 part = ped_partition_new (disk, part_type, NULL, start,
1682 ped_constraint_done (&constraint);
1686 ped_exception_fetch_all ();
1687 if (ped_disk_add_partition (disk, part, &constraint)) {
1688 ped_exception_leave_all ();
1689 switch (_rescue_add_partition (part)) {
1691 ped_constraint_done (&constraint);
1695 ped_disk_remove_partition (disk, part);
1699 goto error_remove_partition;
1702 ped_exception_leave_all ();
1704 ped_partition_destroy (part);
1705 ped_constraint_done (&constraint);
1707 ped_timer_update (g_timer, 1.0);
1711 error_remove_partition:
1712 ped_disk_remove_partition (disk, part);
1713 ped_partition_destroy (part);
1714 ped_constraint_done (&constraint);
1719 do_rescue (PedDevice** dev)
1722 PedSector start = 0, end = 0;
1724 PedGeometry probe_start_region;
1725 PedGeometry probe_end_region;
1727 disk = ped_disk_new (*dev);
1731 if (!command_line_get_sector (_("Start?"), *dev, &start, NULL))
1732 goto error_destroy_disk;
1733 if (!command_line_get_sector (_("End?"), *dev, &end, NULL))
1734 goto error_destroy_disk;
1736 fuzz = PED_MAX (PED_MIN ((end - start) / 10, MEGABYTE_SECTORS(*dev)),
1737 MEGABYTE_SECTORS(*dev) * 16);
1739 ped_geometry_init (&probe_start_region, *dev,
1740 PED_MAX(start - fuzz, 0),
1741 PED_MIN(2 * fuzz, (*dev)->length - (start - fuzz)));
1742 ped_geometry_init (&probe_end_region, *dev,
1743 PED_MAX(end - fuzz, 0),
1744 PED_MIN(2 * fuzz, (*dev)->length - (end - fuzz)));
1746 if (!_rescue_pass (disk, &probe_start_region, &probe_end_region))
1747 goto error_destroy_disk;
1749 ped_disk_destroy (disk);
1751 if ((*dev)->type != PED_DEVICE_FILE)
1752 disk_is_modified = 1;
1757 ped_disk_destroy (disk);
1763 do_resize (PedDevice** dev)
1766 PedPartition *part = NULL;
1768 PedConstraint *constraint;
1769 PedSector start, end;
1770 PedGeometry *range_start = NULL, *range_end = NULL;
1771 PedGeometry new_geom;
1773 disk = ped_disk_new (*dev);
1777 if (!command_line_get_partition (_("Partition number?"), disk, &part))
1778 goto error_destroy_disk;
1779 if (part->type != PED_PARTITION_EXTENDED) {
1780 if (!_partition_warn_busy (part))
1781 goto error_destroy_disk;
1784 start = part->geom.start;
1785 end = part->geom.end;
1786 if (!command_line_get_sector (_("Start?"), *dev, &start, &range_start))
1787 goto error_destroy_disk;
1788 if (!command_line_get_sector (_("End?"), *dev, &end, &range_end))
1789 goto error_destroy_disk;
1791 if (!ped_geometry_init (&new_geom, *dev, start, end - start + 1))
1792 goto error_destroy_disk;
1793 snap_to_boundaries (&new_geom, &part->geom, disk,
1794 range_start, range_end);
1796 if (part->type == PED_PARTITION_EXTENDED) {
1797 constraint = constraint_from_start_end (*dev,
1798 range_start, range_end);
1799 if (!ped_disk_set_partition_geom (disk, part, constraint,
1800 new_geom.start, new_geom.end))
1801 goto error_destroy_constraint;
1802 ped_partition_set_system (part, NULL);
1804 fs = ped_file_system_open (&part->geom);
1806 goto error_destroy_disk;
1807 constraint = constraint_intersect_and_destroy (
1808 ped_file_system_get_resize_constraint (fs),
1809 constraint_from_start_end (
1810 *dev, range_start, range_end));
1811 if (!ped_disk_set_partition_geom (disk, part, constraint,
1812 new_geom.start, new_geom.end))
1813 goto error_close_fs;
1814 if (!ped_file_system_resize (fs, &part->geom, g_timer))
1815 goto error_close_fs;
1816 /* may have changed... eg fat16 -> fat32 */
1817 ped_partition_set_system (part, fs->type);
1818 ped_file_system_close (fs);
1821 ped_disk_commit (disk);
1822 ped_constraint_destroy (constraint);
1823 ped_disk_destroy (disk);
1824 if (range_start != NULL)
1825 ped_geometry_destroy (range_start);
1826 if (range_end != NULL)
1827 ped_geometry_destroy (range_end);
1829 if ((*dev)->type != PED_DEVICE_FILE)
1830 disk_is_modified = 1;
1835 ped_file_system_close (fs);
1836 error_destroy_constraint:
1837 ped_constraint_destroy (constraint);
1839 ped_disk_destroy (disk);
1841 if (range_start != NULL)
1842 ped_geometry_destroy (range_start);
1843 if (range_end != NULL)
1844 ped_geometry_destroy (range_end);
1849 do_rm (PedDevice** dev)
1852 PedPartition* part = NULL;
1854 disk = ped_disk_new (*dev);
1858 if (!command_line_get_partition (_("Partition number?"), disk, &part))
1859 goto error_destroy_disk;
1860 if (!_partition_warn_busy (part))
1861 goto error_destroy_disk;
1863 ped_disk_delete_partition (disk, part);
1864 ped_disk_commit (disk);
1865 ped_disk_destroy (disk);
1867 if ((*dev)->type != PED_DEVICE_FILE)
1868 disk_is_modified = 1;
1873 ped_disk_destroy (disk);
1879 do_select (PedDevice** dev)
1881 PedDevice* new_dev = *dev;
1883 if (!command_line_get_device (_("New device?"), &new_dev))
1885 if (!ped_device_open (new_dev))
1888 ped_device_close (*dev);
1890 print_using_dev (*dev);
1895 do_set (PedDevice** dev)
1898 PedPartition* part = NULL;
1899 PedPartitionFlag flag;
1902 disk = ped_disk_new (*dev);
1906 if (!command_line_get_partition (_("Partition number?"), disk, &part))
1907 goto error_destroy_disk;
1908 if (!command_line_get_part_flag (_("Flag to Invert?"), part, &flag))
1909 goto error_destroy_disk;
1910 state = (ped_partition_get_flag (part, flag) == 0 ? 1 : 0);
1912 if (!is_toggle_mode) {
1913 if (!command_line_get_state (_("New state?"), &state))
1914 goto error_destroy_disk;
1917 if (!ped_partition_set_flag (part, flag, state))
1918 goto error_destroy_disk;
1919 if (!ped_disk_commit (disk))
1920 goto error_destroy_disk;
1921 ped_disk_destroy (disk);
1923 if ((*dev)->type != PED_DEVICE_FILE)
1924 disk_is_modified = 1;
1929 ped_disk_destroy (disk);
1935 do_toggle (PedDevice **dev)
1940 result = do_set (dev);
1947 do_unit (PedDevice** dev)
1949 PedUnit unit = ped_unit_get_default ();
1950 if (!command_line_get_unit (_("Unit?"), &unit))
1952 ped_unit_set_default (unit);
1970 PedFileSystemType* fs_type;
1971 PedDiskType* disk_type;
1972 PedPartitionFlag part_flag;
1977 list = str_list_create (_(flag_msg_start), NULL);
1978 for (part_flag = ped_partition_flag_next (0); part_flag;
1979 part_flag = ped_partition_flag_next (part_flag)) {
1983 str_list_append (list, ", ");
1984 str_list_append (list,
1985 _(ped_partition_flag_get_name (part_flag)));
1987 str_list_append (list, "\n");
1989 flag_msg = str_list_convert (list);
1990 str_list_destroy (list);
1994 list = str_list_create (_(unit_msg_start), NULL);
1995 for (unit = PED_UNIT_FIRST; unit <= PED_UNIT_LAST; unit++) {
1999 str_list_append (list, ", ");
2000 str_list_append (list, ped_unit_get_name (unit));
2002 str_list_append (list, "\n");
2004 unit_msg = str_list_convert (list);
2005 str_list_destroy (list);
2008 list = str_list_create (_(label_type_msg_start), NULL);
2011 for (disk_type = ped_disk_type_get_next (NULL);
2012 disk_type; disk_type = ped_disk_type_get_next (disk_type)) {
2013 if (disk_type->ops->write == NULL)
2019 str_list_append (list, ", ");
2020 str_list_append (list, disk_type->name);
2022 str_list_append (list, "\n");
2024 label_type_msg = str_list_convert (list);
2025 str_list_destroy (list);
2027 /* mkfs - file system types */
2028 list = str_list_create (_(fs_type_msg_start), NULL);
2031 for (fs_type = ped_file_system_type_get_next (NULL);
2032 fs_type; fs_type = ped_file_system_type_get_next (fs_type)) {
2033 if (fs_type->ops->create == NULL)
2039 str_list_append (list, ", ");
2040 str_list_append (list, fs_type->name);
2042 str_list_append (list, "\n");
2044 mkfs_fs_type_msg = str_list_convert (list);
2045 str_list_destroy (list);
2047 /* mkpart - file system types */
2048 list = str_list_create (_(fs_type_msg_start), NULL);
2051 for (fs_type = ped_file_system_type_get_next (NULL);
2052 fs_type; fs_type = ped_file_system_type_get_next (fs_type)) {
2056 str_list_append (list, ", ");
2057 str_list_append (list, fs_type->name);
2059 str_list_append (list, "\n");
2061 mkpart_fs_type_msg = str_list_convert (list);
2062 str_list_destroy (list);
2064 /* resize - file system types */
2065 list = str_list_create (_(resize_msg_start), NULL);
2068 for (fs_type = ped_file_system_type_get_next (NULL);
2069 fs_type; fs_type = ped_file_system_type_get_next (fs_type)) {
2070 if (fs_type->ops->resize == NULL)
2076 str_list_append (list, ", ");
2077 str_list_append (list, fs_type->name);
2079 str_list_append (list, "\n");
2081 resize_fs_type_msg = str_list_convert (list);
2082 str_list_destroy (list);
2089 free (mkfs_fs_type_msg);
2090 free (mkpart_fs_type_msg);
2091 free (resize_fs_type_msg);
2092 free (label_type_msg);
2098 command_register (commands, command_create (
2099 str_list_create_unique ("check", _("check"), NULL),
2102 _("check NUMBER do a simple check on the file "
2105 str_list_create (_(number_msg), NULL), 1));
2107 command_register (commands, command_create (
2108 str_list_create_unique ("cp", _("cp"), NULL),
2111 _("cp [FROM-DEVICE] FROM-NUMBER TO-NUMBER copy file system to another "
2114 str_list_create (_(number_msg), _(device_msg), NULL), 1));
2116 command_register (commands, command_create (
2117 str_list_create_unique ("help", _("help"), NULL),
2120 _("help [COMMAND] print general help, or help "
2125 command_register (commands, command_create (
2126 str_list_create_unique ("mklabel", _("mklabel"), "mktable", _("mktable"), NULL),
2129 _("mklabel,mktable LABEL-TYPE create a new disklabel "
2130 "(partition table)"),
2132 str_list_create (label_type_msg, NULL), 1));
2134 command_register (commands, command_create (
2135 str_list_create_unique ("mkfs", _("mkfs"), NULL),
2138 _("mkfs NUMBER FS-TYPE make a FS-TYPE file "
2139 "system on partititon NUMBER"),
2141 str_list_create (_(number_msg), _(mkfs_fs_type_msg), NULL), 1));
2143 command_register (commands, command_create (
2144 str_list_create_unique ("mkpart", _("mkpart"), NULL),
2147 _("mkpart PART-TYPE [FS-TYPE] START END make a partition"),
2149 str_list_create (_(part_type_msg),
2150 _(mkpart_fs_type_msg),
2153 _("'mkpart' makes a partition without creating a new file system on the "
2154 "partition. FS-TYPE may be specified to set an appropriate partition ID.\n"),
2157 command_register (commands, command_create (
2158 str_list_create_unique ("mkpartfs", _("mkpartfs"), NULL),
2161 _("mkpartfs PART-TYPE FS-TYPE START END make a partition with a "
2164 str_list_create (_(part_type_msg), _(start_end_msg), NULL), 1));
2166 command_register (commands, command_create (
2167 str_list_create_unique ("move", _("move"), NULL),
2170 _("move NUMBER START END move partition NUMBER"),
2172 str_list_create (_(number_msg), _(start_end_msg), NULL), 1));
2174 command_register (commands, command_create (
2175 str_list_create_unique ("name", _("name"), NULL),
2178 _("name NUMBER NAME name partition NUMBER as NAME"),
2180 str_list_create (_(number_msg), _(name_msg), NULL), 1));
2182 command_register (commands, command_create (
2183 str_list_create_unique ("print", _("print"), NULL),
2186 _("print [devices|free|list,all|NUMBER] display the partition table, "
2187 "available devices, free space, all found partitions, or a particular "
2191 _("Without arguments, 'print' displays the entire partition table. However "
2192 "with the following arguments it performs various other actions.\n"),
2193 _(" devices : display all active block devices\n"),
2194 _(" free : display information about free unpartitioned space on the "
2195 "current block device\n"),
2196 _(" list, all : display the partition tables of all active block devices\n"),
2197 _(" NUMBER : display more detailed information about this particular "
2201 command_register (commands, command_create (
2202 str_list_create_unique ("quit", _("quit"), NULL),
2205 _("quit exit program"),
2209 command_register (commands, command_create (
2210 str_list_create_unique ("rescue", _("rescue"), NULL),
2213 _("rescue START END rescue a lost partition near "
2216 str_list_create (_(start_end_msg), NULL), 1));
2218 command_register (commands, command_create (
2219 str_list_create_unique ("resize", _("resize"), NULL),
2222 _("resize NUMBER START END resize partition NUMBER and "
2225 str_list_create (_(number_msg),
2227 _(resize_fs_type_msg), NULL), 1));
2229 command_register (commands, command_create (
2230 str_list_create_unique ("rm", _("rm"), NULL),
2233 _("rm NUMBER delete partition NUMBER"),
2235 str_list_create (_(number_msg), NULL), 1));
2237 command_register (commands, command_create (
2238 str_list_create_unique ("select", _("select"), NULL),
2241 _("select DEVICE choose the device to edit"),
2243 str_list_create (_(device_msg), NULL), 1));
2245 command_register (commands, command_create (
2246 str_list_create_unique ("set", _("set"), NULL),
2249 _("set NUMBER FLAG STATE change the FLAG on partition "
2252 str_list_create (_(number_msg), flag_msg, _(state_msg), NULL), 1));
2254 command_register (commands, command_create (
2255 str_list_create_unique ("toggle", _("toggle"), NULL),
2258 _("toggle [NUMBER [FLAG]] toggle the state of FLAG on "
2259 "partition NUMBER"),
2261 str_list_create (_(number_msg), flag_msg, NULL), 1));
2263 command_register (commands, command_create (
2264 str_list_create_unique ("unit", _("unit"), NULL),
2267 _("unit UNIT set the default unit to UNIT"),
2269 str_list_create (unit_msg, NULL), 1));
2271 command_register (commands, command_create (
2272 str_list_create_unique ("version", _("version"), NULL),
2275 _("version display the version number "
2276 "and copyright information of GNU Parted"),
2279 _("'version' displays copyright and version information corresponding to this "
2280 "copy of GNU Parted\n"),
2290 for (walk = commands; *walk; walk++) {
2291 command_destroy (*walk);
2299 /* intialize i18n */
2301 setlocale(LC_ALL, "");
2302 bindtextdomain(PACKAGE, LOCALEDIR);
2303 textdomain(PACKAGE);
2304 #endif /* ENABLE_NLS */
2310 version_etc (stdout, PROGRAM_NAME, PACKAGE_NAME, VERSION, AUTHORS,
2315 _parse_options (int* argc_ptr, char*** argv_ptr)
2317 int opt, help = 0, list = 0, version = 0, wrong = 0;
2321 opt = getopt_long (*argc_ptr, *argv_ptr, "hilmsv",
2327 case 'h': help = 1; break;
2328 case 'l': list = 1; break;
2329 case 'm': opt_machine_mode = 1; break;
2330 case 's': opt_script_mode = 1; break;
2331 case 'v': version = 1; break;
2332 case PRETEND_INPUT_TTY:
2333 pretend_input_tty = 1;
2335 default: wrong = 1; break;
2341 _("Usage: %s [-hlmsv] [DEVICE [COMMAND [PARAMETERS]]...]\n"),
2348 exit (EXIT_SUCCESS);
2353 exit (EXIT_SUCCESS);
2358 exit (EXIT_SUCCESS);
2361 *argc_ptr -= optind;
2362 *argv_ptr += optind;
2367 _choose_device (int* argc_ptr, char*** argv_ptr)
2371 /* specified on comand line? */
2373 dev = ped_device_get ((*argv_ptr) [0]);
2380 ped_device_probe_all ();
2381 dev = ped_device_get_next (NULL);
2383 if (ped_exception_throw (PED_EXCEPTION_ERROR,
2384 PED_EXCEPTION_RETRY_CANCEL,
2385 _("No device found"))
2386 == PED_EXCEPTION_RETRY)
2393 if (!ped_device_open (dev))
2399 _init (int* argc_ptr, char*** argv_ptr)
2403 #ifdef ENABLE_MTRACE
2413 if (!_parse_options (argc_ptr, argv_ptr))
2414 goto error_done_commands;
2417 if (getuid() != 0 && !opt_script_mode) {
2418 puts (_("WARNING: You are not superuser. Watch out for "
2423 dev = _choose_device (argc_ptr, argv_ptr);
2425 goto error_done_commands;
2427 g_timer = ped_timer_new (_timer_handler, &timer_context);
2429 goto error_done_commands;
2430 timer_context.last_update = 0;
2434 error_done_commands:
2443 _done (PedDevice* dev)
2445 if (dev->boot_dirty && dev->type != PED_DEVICE_FILE) {
2446 ped_exception_throw (
2447 PED_EXCEPTION_WARNING,
2449 _("You should reinstall your boot loader before "
2450 "rebooting. Read section 4 of the Parted User "
2451 "documentation for more information."));
2453 if (!opt_script_mode && !opt_machine_mode && disk_is_modified) {
2454 ped_exception_throw (
2455 PED_EXCEPTION_INFORMATION, PED_EXCEPTION_OK,
2456 _("You may need to update /etc/fstab.\n"));
2459 ped_device_close (dev);
2461 ped_timer_destroy (g_timer);
2468 main (int argc, char** argv)
2473 program_name = argv[0];
2474 atexit (close_stdout);
2476 dev = _init (&argc, &argv);
2480 if (argc || opt_script_mode)
2481 status = non_interactive_mode (&dev, commands, argc, argv);
2483 status = interactive_mode (&dev, commands);