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"
31 "<http://parted.alioth.debian.org/cgi-bin/trac.cgi/browser/AUTHORS>"
33 /* The official name of this program (e.g., no `g' prefix). */
34 #define PROGRAM_NAME "parted"
36 #define N_(String) String
40 # define _(String) dgettext (PACKAGE, String)
42 # define _(String) (String)
43 #endif /* ENABLE_NLS */
45 #include <parted/parted.h>
46 #include <parted/debug.h>
62 /* minimum amount of free space to leave, or maximum amount to gobble up */
63 #define MIN_FREESPACE (1000 * 2) /* 1000k */
65 static int MEGABYTE_SECTORS (PedDevice* dev)
67 return PED_MEGABYTE_SIZE / dev->sector_size;
70 /* For long options that have no equivalent short option, use a
71 non-character as a pseudo short option, starting with CHAR_MAX + 1. */
74 PRETEND_INPUT_TTY = CHAR_MAX + 1,
80 time_t predicted_time_left;
83 static struct option const options[] = {
84 /* name, has-arg, string-return-val, char-return-val */
85 {"help", 0, NULL, 'h'},
86 {"list", 0, NULL, 'l'},
87 {"machine", 0, NULL, 'm'},
88 {"script", 0, NULL, 's'},
89 {"version", 0, NULL, 'v'},
90 {"-pretend-input-tty", 0, NULL, PRETEND_INPUT_TTY},
94 static const char *const options_help [][2] = {
95 {"help", N_("displays this help message")},
96 {"list", N_("lists partition layout on all block devices")},
97 {"machine", N_("displays machine parseable output")},
98 {"script", N_("never prompts for user intervention")},
99 {"version", N_("displays the version")},
103 int opt_script_mode = 0;
104 int pretend_input_tty = 0;
105 int opt_machine_mode = 0;
106 int disk_is_modified = 0;
107 int is_toggle_mode = 0;
109 static const char* number_msg = N_(
110 "NUMBER is the partition number used by Linux. On MS-DOS disk labels, the "
111 "primary partitions number from 1 to 4, logical partitions from 5 onwards.\n");
113 static const char* label_type_msg_start = N_("LABEL-TYPE is one of: ");
114 static const char* flag_msg_start = N_("FLAG is one of: ");
115 static const char* unit_msg_start = N_("UNIT is one of: ");
116 static const char* part_type_msg = N_("PART-TYPE is one of: primary, logical, "
118 static const char* fs_type_msg_start = N_("FS-TYPE is one of: ");
119 static const char* start_end_msg = N_("START and END are disk locations, such as "
120 "4GB or 10%. Negative values count from the end of the disk. "
121 "For example, -1s specifies exactly the last sector.\n");
122 static const char* state_msg = N_("STATE is one of: on, off\n");
123 static const char* device_msg = N_("DEVICE is usually /dev/hda or /dev/sda\n");
124 static const char* name_msg = N_("NAME is any word you want\n");
125 static const char* resize_msg_start = N_("The partition must have one of the "
126 "following FS-TYPEs: ");
128 static const char* copyright_msg = N_(
129 "Copyright (C) 1998 - 2006 Free Software Foundation, Inc.\n"
130 "This program is free software, covered by the GNU General Public License.\n"
132 "This program is distributed in the hope that it will be useful,\n"
133 "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
134 "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
135 "GNU General Public License for more details.\n\n");
137 static char* label_type_msg;
138 static char* flag_msg;
139 static char* unit_msg;
141 static char* mkfs_fs_type_msg;
142 static char* mkpart_fs_type_msg;
143 static char* resize_fs_type_msg;
145 static Command* commands [256] = {NULL};
146 static PedTimer* g_timer;
147 static TimerContext timer_context;
149 static int _print_list ();
150 static void _done (PedDevice* dev);
153 _timer_handler (PedTimer* timer, void* context)
155 TimerContext* tcontext = (TimerContext*) context;
158 if (opt_script_mode || !isatty(fileno(stdout)))
161 if (tcontext->last_update != timer->now && timer->now > timer->start) {
162 tcontext->predicted_time_left
163 = timer->predicted_end - timer->now;
164 tcontext->last_update = timer->now;
170 if (draw_this_time) {
173 if (timer->state_name)
174 printf ("%s... ", timer->state_name);
175 printf (_("%0.f%%\t(time left %.2d:%.2d)"),
177 (int) (tcontext->predicted_time_left / 60),
178 (int) (tcontext->predicted_time_left % 60));
185 _partition_warn_busy (PedPartition* part)
189 if (ped_partition_is_busy (part)) {
190 path = ped_partition_get_path (part);
191 ped_exception_throw (
193 PED_EXCEPTION_CANCEL,
194 _("Partition %s is being used. You must unmount it "
195 "before you modify it with Parted."),
204 _disk_warn_busy (PedDisk* disk)
206 if (ped_device_is_busy (disk->dev))
207 return ped_exception_throw (
209 ? PED_EXCEPTION_ERROR
210 : PED_EXCEPTION_WARNING),
211 PED_EXCEPTION_IGNORE_CANCEL,
212 _("Partition(s) on %s are being used."),
213 disk->dev->path) == PED_EXCEPTION_IGNORE;
219 _partition_warn_loss ()
221 return ped_exception_throw (
222 PED_EXCEPTION_WARNING,
223 PED_EXCEPTION_YES_NO,
224 _("The existing file system will be destroyed and "
225 "all data on the partition will be lost. Do "
226 "you want to continue?"),
227 NULL) == PED_EXCEPTION_YES;
231 _disk_warn_loss (PedDisk* disk)
233 return ped_exception_throw (
234 PED_EXCEPTION_WARNING,
235 PED_EXCEPTION_YES_NO,
236 _("The existing disk label on %s will be destroyed "
237 "and all data on this disk will be lost. Do you "
238 "want to continue?"),
239 disk->dev->path) == PED_EXCEPTION_YES;
242 /* This function changes "sector" to "new_sector" if the new value lies
243 * within the required range.
246 snap (PedSector* sector, PedSector new_sector, PedGeometry* range)
248 PED_ASSERT (ped_geometry_test_sector_inside (range, *sector), return 0);
249 if (!ped_geometry_test_sector_inside (range, new_sector))
251 *sector = new_sector;
262 enum { /* Don't change these values */
267 /* Find the prefered way to adjust the sector s inside range.
268 * If a move isn't allowed or is out of range it can't be selected.
269 * what contains SECT_START if the sector to adjust is a start sector
270 * or SECT_END if it's an end one.
271 * The prefered move is to the nearest allowed boundary of the part
272 * partition (if at equal distance: to start if SECT_START or to end
274 * The distance is returned in dist.
277 prefer_snap (PedSector s, int what, PedGeometry* range, EMoves* allow,
278 PedPartition* part, PedSector* dist)
280 PedSector up_dist = -1, down_dist = -1;
284 PED_ASSERT (what == SECT_START || what == SECT_END, return 0);
286 if (!(*allow & (MOVE_UP | MOVE_DOWN))) {
291 if (*allow & MOVE_UP) {
292 new_sect = part->geom.end + 1 + what;
293 if (ped_geometry_test_sector_inside (range, new_sect))
294 up_dist = new_sect - s;
299 if (*allow & MOVE_DOWN) {
300 new_sect = part->geom.start + what;
301 if (ped_geometry_test_sector_inside (range, new_sect))
302 down_dist = s - new_sect;
304 *allow &= ~MOVE_DOWN;
308 if ((*allow & MOVE_UP) && (*allow & MOVE_DOWN)) {
309 if (down_dist < up_dist || (down_dist == up_dist
310 && what == SECT_START) )
312 else if (up_dist < down_dist || (down_dist == up_dist
313 && what == SECT_END) )
316 PED_ASSERT (0, return 0);
317 } else if (*allow & MOVE_UP)
319 else if (*allow & MOVE_DOWN)
322 *dist = ( move == MOVE_DOWN ? down_dist :
323 ( move == MOVE_UP ? up_dist :
328 /* Snaps a partition to nearby partition boundaries. This is useful for
329 * gobbling up small amounts of free space, and also for reinterpreting small
330 * changes to a partition as non-changes (eg: perhaps the user only wanted to
331 * resize the end of a partition).
332 * Note that this isn't the end of the story... this function is
333 * always called before the constraint solver kicks in. So you don't need to
334 * worry too much about inadvertantly creating overlapping partitions, etc.
337 snap_to_boundaries (PedGeometry* new_geom, PedGeometry* old_geom,
339 PedGeometry* start_range, PedGeometry* end_range)
341 PedPartition* start_part;
342 PedPartition* end_part;
343 PedSector start = new_geom->start;
344 PedSector end = new_geom->end;
345 PedSector start_dist = -1, end_dist = -1;
346 EMoves start_allow, end_allow, start_want, end_want;
349 start_want = end_want = MOVE_NO;
350 start_allow = end_allow = MOVE_STILL | MOVE_UP | MOVE_DOWN;
352 start_part = ped_disk_get_partition_by_sector (disk, start);
353 end_part = ped_disk_get_partition_by_sector (disk, end);
354 adjacent = (start_part->geom.end + 1 == end_part->geom.start);
356 /* If we can snap to old_geom, then we will... */
357 /* and this will enforce the snapped positions */
359 if (snap (&start, old_geom->start, start_range))
360 start_allow = MOVE_STILL;
361 if (snap (&end, old_geom->end, end_range))
362 end_allow = MOVE_STILL;
365 /* If start and end are on the same partition, we */
366 /* don't allow them to cross. */
367 if (start_part == end_part) {
368 start_allow &= ~MOVE_UP;
369 end_allow &= ~MOVE_DOWN;
372 /* Let's find our way */
373 start_want = prefer_snap (start, SECT_START, start_range, &start_allow,
374 start_part, &start_dist );
375 end_want = prefer_snap (end, SECT_END, end_range, &end_allow,
376 end_part, &end_dist );
378 PED_ASSERT (start_dist >= 0 && end_dist >= 0, return);
380 /* If start and end are on adjacent partitions, */
381 /* and if they would prefer crossing, then refrain */
382 /* the farthest to do so. */
383 if (adjacent && start_want == MOVE_UP && end_want == MOVE_DOWN) {
384 if (end_dist < start_dist) {
385 start_allow &= ~MOVE_UP;
386 start_want = prefer_snap (start, SECT_START,
387 start_range, &start_allow,
388 start_part, &start_dist );
389 PED_ASSERT (start_dist >= 0, return);
391 end_allow &= ~MOVE_DOWN;
392 end_want = prefer_snap (end, SECT_END,
393 end_range, &end_allow,
394 end_part, &end_dist );
395 PED_ASSERT (end_dist >= 0, return);
400 start = ( start_want == MOVE_DOWN ? start_part->geom.start :
401 ( start_want == MOVE_UP ? start_part->geom.end + 1 :
403 end = ( end_want == MOVE_DOWN ? end_part->geom.start - 1 :
404 ( end_want == MOVE_UP ? end_part->geom.end :
406 PED_ASSERT (ped_geometry_test_sector_inside(start_range,start), return);
407 PED_ASSERT (ped_geometry_test_sector_inside (end_range, end), return);
408 PED_ASSERT (start <= end,
409 PED_DEBUG (0, "start = %d, end = %d\n", start, end));
410 ped_geometry_set (new_geom, start, end - start + 1);
413 /* This functions constructs a constraint from the following information:
414 * start, is_start_exact, end, is_end_exact.
416 * If is_start_exact == 1, then the constraint requires start be as given in
417 * "start". Otherwise, the constraint does not set any requirements on the
420 static PedConstraint*
421 constraint_from_start_end (PedDevice* dev, PedGeometry* range_start,
422 PedGeometry* range_end)
424 return ped_constraint_new (ped_alignment_any, ped_alignment_any,
425 range_start, range_end, 1, dev->length);
428 static PedConstraint*
429 constraint_intersect_and_destroy (PedConstraint* a, PedConstraint* b)
431 PedConstraint* result = ped_constraint_intersect (a, b);
432 ped_constraint_destroy (a);
433 ped_constraint_destroy (b);
438 help_on (char* topic)
442 cmd = command_get (commands, topic);
445 command_print_help (cmd);
449 do_check (PedDevice** dev)
453 PedPartition* part = NULL;
455 disk = ped_disk_new (*dev);
459 if (!command_line_get_partition (_("Partition number?"), disk, &part))
460 goto error_destroy_disk;
461 if (!_partition_warn_busy (part))
462 goto error_destroy_disk;
464 if (!ped_disk_check (disk))
465 goto error_destroy_disk;
467 fs = ped_file_system_open (&part->geom);
469 goto error_destroy_disk;
470 if (!ped_file_system_check (fs, g_timer))
472 ped_file_system_close (fs);
473 ped_disk_destroy (disk);
477 ped_file_system_close (fs);
479 ped_disk_destroy (disk);
485 do_cp (PedDevice** dev)
489 PedPartition* src = NULL;
490 PedPartition* dst = NULL;
491 PedFileSystem* src_fs;
492 PedFileSystem* dst_fs;
493 PedFileSystemType* dst_fs_type;
495 dst_disk = ped_disk_new (*dev);
500 if (!command_line_is_integer ()) {
501 if (!command_line_get_disk (_("Source device?"), &src_disk))
502 goto error_destroy_disk;
505 if (!command_line_get_partition (_("Source partition number?"),
507 goto error_destroy_disk;
508 if (src->type == PED_PARTITION_EXTENDED) {
509 ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
510 _("Can't copy an extended partition."));
511 goto error_destroy_disk;
513 if (!_partition_warn_busy (src))
514 goto error_destroy_disk;
516 if (!command_line_get_partition (_("Destination partition number?"),
518 goto error_destroy_disk;
519 if (!_partition_warn_busy (dst))
520 goto error_destroy_disk;
523 src_fs = ped_file_system_open (&src->geom);
525 goto error_destroy_disk;
526 dst_fs = ped_file_system_copy (src_fs, &dst->geom, g_timer);
528 goto error_close_src_fs;
529 dst_fs_type = dst_fs->type; /* may be different to src_fs->type */
530 ped_file_system_close (src_fs);
531 ped_file_system_close (dst_fs);
533 /* update the partition table, close disks */
534 if (!ped_partition_set_system (dst, dst_fs_type))
535 goto error_destroy_disk;
536 if (!ped_disk_commit (dst_disk))
537 goto error_destroy_disk;
538 if (src_disk != dst_disk)
539 ped_disk_destroy (src_disk);
540 ped_disk_destroy (dst_disk);
542 if ((*dev)->type != PED_DEVICE_FILE)
543 disk_is_modified = 1;
548 ped_file_system_close (src_fs);
550 if (src_disk && src_disk != dst_disk)
551 ped_disk_destroy (src_disk);
552 ped_disk_destroy (dst_disk);
558 print_commands_help ()
562 for (i=0; commands [i]; i++)
563 command_print_summary (commands [i]);
567 print_options_help ()
571 for (i=0; options_help [i][0]; i++) {
572 printf (" -%c, --%-23.23s %s\n",
573 options_help [i][0][0],
575 _(options_help [i][1]));
580 do_help (PedDevice** dev)
582 if (command_line_get_word_count ()) {
583 char* word = command_line_pop_word ();
589 print_commands_help();
595 do_mklabel (PedDevice** dev)
598 const PedDiskType* type = ped_disk_probe (*dev);
600 ped_exception_fetch_all ();
601 disk = ped_disk_new (*dev);
602 if (!disk) ped_exception_catch ();
603 ped_exception_leave_all ();
606 if (!_disk_warn_busy (disk))
607 goto error_destroy_disk;
608 if (!opt_script_mode && !_disk_warn_loss (disk))
609 goto error_destroy_disk;
611 ped_disk_destroy (disk);
614 if (!command_line_get_disk_type (_("New disk label type?"), &type))
617 disk = ped_disk_new_fresh (*dev, type);
621 if (!ped_disk_commit (disk))
622 goto error_destroy_disk;
623 ped_disk_destroy (disk);
625 if ((*dev)->type != PED_DEVICE_FILE)
626 disk_is_modified = 1;
631 ped_disk_destroy (disk);
637 do_mkfs (PedDevice** dev)
640 PedPartition* part = NULL;
641 const PedFileSystemType* type = ped_file_system_type_get ("ext2");
644 disk = ped_disk_new (*dev);
648 if (!opt_script_mode && !_partition_warn_loss())
649 goto error_destroy_disk;
651 if (!command_line_get_partition (_("Partition number?"), disk, &part))
652 goto error_destroy_disk;
653 if (!_partition_warn_busy (part))
654 goto error_destroy_disk;
655 if (!command_line_get_fs_type (_("File system type?"), &type))
656 goto error_destroy_disk;
658 fs = ped_file_system_create (&part->geom, type, g_timer);
660 goto error_destroy_disk;
661 ped_file_system_close (fs);
663 if (!ped_partition_set_system (part, type))
664 goto error_destroy_disk;
665 if (ped_partition_is_flag_available (part, PED_PARTITION_LBA))
666 ped_partition_set_flag (part, PED_PARTITION_LBA, 1);
667 if (!ped_disk_commit (disk))
668 goto error_destroy_disk;
669 ped_disk_destroy (disk);
671 if ((*dev)->type != PED_DEVICE_FILE)
672 disk_is_modified = 1;
677 ped_disk_destroy (disk);
683 do_mkpart (PedDevice** dev)
687 PedPartitionType part_type;
688 const PedFileSystemType* fs_type = ped_file_system_type_get ("ext2");
689 PedSector start = 0, end = 0;
690 PedGeometry *range_start = NULL, *range_end = NULL;
691 PedConstraint* user_constraint;
692 PedConstraint* dev_constraint;
693 PedConstraint* final_constraint;
695 char* part_name = NULL;
696 char *start_usr = NULL, *end_usr = NULL;
697 char *start_sol = NULL, *end_sol = NULL;
699 disk = ped_disk_new (*dev);
703 if (!ped_disk_type_check_feature (disk->type, PED_DISK_TYPE_EXTENDED)) {
704 part_type = PED_PARTITION_NORMAL;
706 if (!command_line_get_part_type (_("Partition type?"),
708 goto error_destroy_disk;
711 /* The undocumented feature that mkpart sometimes takes a
712 partition name is next to useless, at least with a dvh
713 partition table, since it makes the "mkpart" command
714 fail unconditionally for a primary partition. E.g.,
715 mkpart primary any-name xfs 4096s 5000s
716 requires the name, yet always fails, saying that only
717 logical partitions may have names.
718 If you want a name, use parted's separate "name" command. */
720 if (ped_disk_type_check_feature (disk->type,
721 PED_DISK_TYPE_PARTITION_NAME)
722 && ! (strcmp (disk->type->name, "dvh") == 0
723 && part_type != PED_PARTITION_LOGICAL))
724 part_name = command_line_get_word (_("Partition name?"),
727 peek_word = command_line_peek_word ();
728 if (part_type == PED_PARTITION_EXTENDED
729 || (peek_word && isdigit (peek_word[0]))) {
732 if (!command_line_get_fs_type (_("File system type?"),
734 goto error_destroy_disk;
738 if (!command_line_get_sector (_("Start?"), *dev, &start, &range_start))
739 goto error_destroy_disk;
740 if (!command_line_get_sector (_("End?"), *dev, &end, &range_end))
741 goto error_destroy_disk;
743 /* processing starts here */
744 part = ped_partition_new (disk, part_type, fs_type, start, end);
746 goto error_destroy_disk;
748 snap_to_boundaries (&part->geom, NULL, disk, range_start, range_end);
750 /* create constraints */
751 user_constraint = constraint_from_start_end (*dev, range_start,
753 PED_ASSERT (user_constraint != NULL, return 0);
755 dev_constraint = ped_device_get_constraint (*dev);
756 PED_ASSERT (dev_constraint != NULL, return 0);
758 final_constraint = ped_constraint_intersect (user_constraint,
760 ped_constraint_destroy (user_constraint);
761 ped_constraint_destroy (dev_constraint);
762 if (!final_constraint)
763 goto error_destroy_simple_constraints;
765 /* subject to partition constraint */
766 ped_exception_fetch_all();
767 bool added_ok = ped_disk_add_partition (disk, part, final_constraint);
768 ped_constraint_destroy (final_constraint);
770 ped_exception_leave_all();
772 if (ped_disk_add_partition (disk, part,
773 ped_constraint_any (*dev))) {
774 start_usr = ped_unit_format (*dev, start);
775 end_usr = ped_unit_format (*dev, end);
776 start_sol = ped_unit_format (*dev, part->geom.start);
777 end_sol = ped_unit_format (*dev, part->geom.end);
779 /* In script mode failure to use specified values is fatal.
780 * However, in interactive mode, it merely elicits a warning
781 * and a prompt for whether to proceed. The same appies for
782 * do_mkpartfs function.
784 switch (ped_exception_throw (
786 ? PED_EXCEPTION_ERROR
787 : PED_EXCEPTION_WARNING),
789 ? PED_EXCEPTION_CANCEL
790 : PED_EXCEPTION_YES_NO),
791 _("You requested a partition from %s to %s.\n"
792 "The closest location we can manage is "
794 start_usr, end_usr, start_sol, end_sol,
795 (opt_script_mode ? ""
796 : _("\nIs this still acceptable to you?"))))
798 case PED_EXCEPTION_YES:
799 /* all is well in this state */
801 case PED_EXCEPTION_NO:
802 case PED_EXCEPTION_UNHANDLED:
804 /* undo partition addition */
805 goto error_remove_part;
808 goto error_remove_part;
811 ped_exception_leave_all();
813 ped_exception_catch();
815 /* set minor attributes */
817 PED_ASSERT (ped_partition_set_name (part, part_name), return 0);
818 if (!ped_partition_set_system (part, fs_type))
819 goto error_destroy_disk;
820 if (ped_partition_is_flag_available (part, PED_PARTITION_LBA))
821 ped_partition_set_flag (part, PED_PARTITION_LBA, 1);
823 if (!ped_disk_commit (disk))
824 goto error_destroy_disk;
827 ped_disk_destroy (disk);
829 if (range_start != NULL)
830 ped_geometry_destroy (range_start);
831 if (range_end != NULL)
832 ped_geometry_destroy (range_end);
839 if ((*dev)->type != PED_DEVICE_FILE)
840 disk_is_modified = 1;
845 ped_disk_remove_partition (disk, part);
846 error_destroy_simple_constraints:
847 ped_partition_destroy (part);
849 ped_disk_destroy (disk);
851 if (range_start != NULL)
852 ped_geometry_destroy (range_start);
853 if (range_end != NULL)
854 ped_geometry_destroy (range_end);
865 do_mkpartfs (PedDevice** dev)
869 PedPartitionType part_type;
870 const PedFileSystemType* fs_type = ped_file_system_type_get ("ext2");
871 PedSector start = 0, end = 0;
872 PedGeometry *range_start = NULL, *range_end = NULL;
873 PedConstraint* user_constraint;
874 PedConstraint* dev_constraint;
875 PedConstraint* final_constraint;
877 char* part_name = NULL;
878 char *start_usr = NULL, *end_usr = NULL;
879 char *start_sol = NULL, *end_sol = NULL;
881 disk = ped_disk_new (*dev);
885 if (!ped_disk_type_check_feature (disk->type, PED_DISK_TYPE_EXTENDED)) {
886 part_type = PED_PARTITION_NORMAL;
888 if (!command_line_get_part_type (_("Partition type?"),
890 goto error_destroy_disk;
893 if (ped_disk_type_check_feature (disk->type,
894 PED_DISK_TYPE_PARTITION_NAME))
895 part_name = command_line_get_word (_("Partition name?"),
898 if (part_type == PED_PARTITION_EXTENDED) {
899 ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
900 _("An extended partition cannot hold a file system. "
901 "Did you want mkpart?"));
902 goto error_destroy_disk;
905 if (!command_line_get_fs_type (_("File system type?"), &fs_type))
906 goto error_destroy_disk;
907 if (!command_line_get_sector (_("Start?"), *dev, &start,
909 goto error_destroy_disk;
910 if (!command_line_get_sector (_("End?"), *dev, &end, &range_end))
911 goto error_destroy_disk;
913 /* attempt to create the partition now */
914 part = ped_partition_new (disk, part_type, fs_type, start, end);
916 goto error_destroy_disk;
918 snap_to_boundaries (&part->geom, NULL, disk, range_start, range_end);
920 /* create constraints */
921 user_constraint = constraint_from_start_end (*dev, range_start,
923 PED_ASSERT (user_constraint != NULL, return 0);
925 dev_constraint = ped_device_get_constraint (*dev);
926 PED_ASSERT (dev_constraint != NULL, return 0);
928 final_constraint = ped_constraint_intersect (user_constraint,
930 ped_constraint_destroy (user_constraint);
931 ped_constraint_destroy (dev_constraint);
932 if (!final_constraint)
933 goto error_destroy_simple_constraints;
935 /* subject to partition constraint */
936 ped_exception_fetch_all();
937 bool added_ok = ped_disk_add_partition (disk, part, final_constraint);
938 ped_constraint_destroy (final_constraint);
940 ped_exception_leave_all();
942 if (ped_disk_add_partition (disk, part,
943 ped_constraint_any (*dev))) {
944 start_usr = ped_unit_format (*dev, start);
945 end_usr = ped_unit_format (*dev, end);
946 start_sol = ped_unit_format (*dev, part->geom.start);
947 end_sol = ped_unit_format (*dev, part->geom.end);
949 switch (ped_exception_throw (
951 ? PED_EXCEPTION_ERROR
952 : PED_EXCEPTION_WARNING),
954 ? PED_EXCEPTION_CANCEL
955 : PED_EXCEPTION_YES_NO),
956 _("You requested a partition from %s to %s.\n"
957 "The closest location we can manage is "
959 start_usr, end_usr, start_sol, end_sol,
960 (opt_script_mode ? ""
961 : _("\nIs this still acceptable to you?"))))
963 case PED_EXCEPTION_YES:
964 /* all is well in this state */
966 case PED_EXCEPTION_NO:
967 case PED_EXCEPTION_UNHANDLED:
969 /* undo partition addition */
970 goto error_remove_part;
973 goto error_remove_part;
976 ped_exception_leave_all();
978 ped_exception_catch();
980 /* set LBA flag automatically if available */
981 if (ped_partition_is_flag_available (part, PED_PARTITION_LBA))
982 ped_partition_set_flag (part, PED_PARTITION_LBA, 1);
985 fs = ped_file_system_create (&part->geom, fs_type, g_timer);
987 goto error_destroy_disk;
988 ped_file_system_close (fs);
990 if (!ped_partition_set_system (part, fs_type))
991 goto error_destroy_disk;
993 if (!ped_disk_commit (disk))
994 goto error_destroy_disk;
998 ped_disk_destroy (disk);
1000 if (range_start != NULL)
1001 ped_geometry_destroy (range_start);
1002 if (range_end != NULL)
1003 ped_geometry_destroy (range_end);
1010 if ((*dev)->type != PED_DEVICE_FILE)
1011 disk_is_modified = 1;
1016 ped_disk_remove_partition (disk, part);
1017 error_destroy_simple_constraints:
1018 ped_partition_destroy (part);
1020 ped_disk_destroy (disk);
1022 if (range_start != NULL)
1023 ped_geometry_destroy (range_start);
1024 if (range_end != NULL)
1025 ped_geometry_destroy (range_end);
1036 do_move (PedDevice** dev)
1039 PedPartition* part = NULL;
1041 PedFileSystem* fs_copy;
1042 PedConstraint* constraint;
1043 PedSector start = 0, end = 0;
1044 PedGeometry *range_start = NULL, *range_end = NULL;
1045 PedGeometry old_geom, new_geom;
1047 disk = ped_disk_new (*dev);
1051 if (!command_line_get_partition (_("Partition number?"), disk, &part))
1052 goto error_destroy_disk;
1053 if (!_partition_warn_busy (part))
1054 goto error_destroy_disk;
1055 if (part->type == PED_PARTITION_EXTENDED) {
1056 ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
1057 _("Can't move an extended partition."));
1058 goto error_destroy_disk;
1060 old_geom = part->geom;
1061 fs = ped_file_system_open (&old_geom);
1063 goto error_destroy_disk;
1065 /* get new target */
1066 if (!command_line_get_sector (_("Start?"), *dev, &start, &range_start))
1067 goto error_close_fs;
1068 end = start + old_geom.length - 1;
1069 if (!command_line_get_sector (_("End?"), *dev, &end, &range_end))
1070 goto error_close_fs;
1072 /* set / test on "disk" */
1073 if (!ped_geometry_init (&new_geom, *dev, start, end - start + 1))
1074 goto error_close_fs;
1075 snap_to_boundaries (&new_geom, NULL, disk, range_start, range_end);
1077 constraint = constraint_intersect_and_destroy (
1078 ped_file_system_get_copy_constraint (fs, *dev),
1079 constraint_from_start_end(*dev,range_start,range_end));
1080 if (!ped_disk_set_partition_geom (disk, part, constraint,
1081 new_geom.start, new_geom.end))
1082 goto error_destroy_constraint;
1083 ped_constraint_destroy (constraint);
1084 if (ped_geometry_test_overlap (&old_geom, &part->geom)) {
1085 ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
1086 _("Can't move a partition onto itself. Try using "
1087 "resize, perhaps?"));
1088 goto error_close_fs;
1092 fs_copy = ped_file_system_copy (fs, &part->geom, g_timer);
1094 goto error_close_fs;
1095 ped_file_system_close (fs_copy);
1096 ped_file_system_close (fs);
1097 if (!ped_disk_commit (disk))
1098 goto error_destroy_disk;
1099 ped_disk_destroy (disk);
1100 if (range_start != NULL)
1101 ped_geometry_destroy (range_start);
1102 if (range_end != NULL)
1103 ped_geometry_destroy (range_end);
1105 if ((*dev)->type != PED_DEVICE_FILE)
1106 disk_is_modified = 1;
1110 error_destroy_constraint:
1111 ped_constraint_destroy (constraint);
1113 ped_file_system_close (fs);
1115 ped_disk_destroy (disk);
1117 if (range_start != NULL)
1118 ped_geometry_destroy (range_start);
1119 if (range_end != NULL)
1120 ped_geometry_destroy (range_end);
1125 do_name (PedDevice** dev)
1128 PedPartition* part = NULL;
1131 disk = ped_disk_new (*dev);
1135 if (!command_line_get_partition (_("Partition number?"), disk, &part))
1136 goto error_destroy_disk;
1138 name = command_line_get_word (_("Partition name?"),
1139 ped_partition_get_name (part), NULL, 0);
1141 goto error_destroy_disk;
1142 if (!ped_partition_set_name (part, name))
1143 goto error_free_name;
1146 if (!ped_disk_commit (disk))
1147 goto error_destroy_disk;
1148 ped_disk_destroy (disk);
1154 ped_disk_destroy (disk);
1160 partition_print_flags (PedPartition* part)
1162 PedPartitionFlag flag;
1165 char* res = ped_malloc(1);
1171 for (flag = ped_partition_flag_next (0); flag;
1172 flag = ped_partition_flag_next (flag)) {
1173 if (ped_partition_get_flag (part, flag)) {
1178 ped_realloc (&_res, strlen (res)
1181 strncat (res, ", ", 2);
1184 name = _(ped_partition_flag_get_name (flag));
1186 ped_realloc (&_res, strlen (res) + 1
1189 strncat (res, name, 21);
1196 /* Prints a sector out, first in compact form, and then with a percentage.
1200 print_sector_compact_and_percent (PedSector sector, PedDevice* dev)
1205 if (ped_unit_get_default() == PED_UNIT_PERCENT)
1206 compact = ped_unit_format (dev, sector);
1208 compact = ped_unit_format_custom (dev, sector,
1211 percent = ped_unit_format_custom (dev, sector, PED_UNIT_PERCENT);
1213 printf ("%s (%s)\n", compact, percent);
1220 partition_print (PedPartition* part)
1223 PedConstraint* resize_constraint;
1226 fs = ped_file_system_open (&part->geom);
1232 flags = partition_print_flags (part);
1234 printf (_("Minor: %d\n"), part->num);
1235 printf (_("Flags: %s\n"), flags);
1236 printf (_("File System: %s\n"), fs->type->name);
1237 fputs (_("Size: "), stdout);
1238 print_sector_compact_and_percent (part->geom.length, part->geom.dev);
1240 resize_constraint = ped_file_system_get_resize_constraint (fs);
1241 if (resize_constraint) {
1242 fputs (_("Minimum size: "), stdout);
1243 print_sector_compact_and_percent (resize_constraint->min_size,
1245 fputs (_("Maximum size: "), stdout);
1246 print_sector_compact_and_percent (resize_constraint->max_size,
1248 ped_constraint_destroy (resize_constraint);
1254 ped_file_system_close (fs);
1260 do_print (PedDevice** dev)
1262 PedUnit default_unit;
1267 int has_devices_arg = 0;
1268 int has_free_arg = 0;
1269 int has_list_arg = 0;
1270 int has_num_arg = 0;
1271 const char *const transport[] = {"unknown", "scsi", "ide", "dac960",
1272 "cpqarray", "file", "ataraid", "i2o",
1273 "ubd", "dasd", "viodasd", "sx8", "dm",
1274 "xvd", "sd/mmc", "virtblk"};
1282 wchar_t* table_rendered;
1284 disk = ped_disk_new (*dev);
1288 peek_word = command_line_peek_word ();
1290 if (strncmp (peek_word, "devices", 7) == 0) {
1291 command_line_pop_word();
1292 has_devices_arg = 1;
1294 else if (strncmp (peek_word, "free", 4) == 0) {
1295 command_line_pop_word ();
1298 else if (strncmp (peek_word, "list", 4) == 0 ||
1299 strncmp (peek_word, "all", 3) == 0) {
1300 command_line_pop_word();
1304 has_num_arg = isdigit(peek_word[0]);
1309 if (has_devices_arg) {
1311 PedDevice* current_dev = NULL;
1313 ped_device_probe_all();
1315 while ((current_dev = ped_device_get_next(current_dev))) {
1316 end = ped_unit_format_byte (current_dev,
1318 * current_dev->sector_size);
1319 printf ("%s (%s)\n", current_dev->path, end);
1323 dev_name = xstrdup ((*dev)->path);
1324 ped_device_free_all ();
1326 *dev = ped_device_get (dev_name);
1329 if (!ped_device_open (*dev))
1337 else if (has_list_arg)
1338 return _print_list ();
1340 else if (has_num_arg) {
1341 PedPartition* part = NULL;
1343 if (command_line_get_partition ("", disk, &part))
1344 status = partition_print (part);
1345 ped_disk_destroy (disk);
1349 start = ped_unit_format (*dev, 0);
1350 default_unit = ped_unit_get_default ();
1351 end = ped_unit_format_byte (*dev, (*dev)->length * (*dev)->sector_size
1352 - (default_unit == PED_UNIT_CHS ||
1353 default_unit == PED_UNIT_CYLINDER));
1355 if (opt_machine_mode) {
1356 switch (default_unit) {
1357 case PED_UNIT_CHS: puts ("CHS;");
1359 case PED_UNIT_CYLINDER: puts ("CYL;");
1361 default: puts ("BYT;");
1365 printf ("%s:%s:%s:%lld:%lld:%s:%s;\n",
1366 (*dev)->path, end, transport[(*dev)->type],
1367 (*dev)->sector_size, (*dev)->phys_sector_size,
1368 disk->type->name, (*dev)->model);
1370 printf (_("Model: %s (%s)\n"),
1371 (*dev)->model, transport[(*dev)->type]);
1372 printf (_("Disk %s: %s\n"), (*dev)->path, end);
1373 printf (_("Sector size (logical/physical): %lldB/%lldB\n"),
1374 (*dev)->sector_size, (*dev)->phys_sector_size);
1380 if (ped_unit_get_default () == PED_UNIT_CHS
1381 || ped_unit_get_default () == PED_UNIT_CYLINDER) {
1382 PedCHSGeometry* chs = &(*dev)->bios_geom;
1383 char* cyl_size = ped_unit_format_custom (*dev,
1384 chs->heads * chs->sectors,
1387 if (opt_machine_mode) {
1388 printf ("%d:%d:%d:%s;\n",
1389 chs->cylinders, chs->heads, chs->sectors, cyl_size);
1391 printf (_("BIOS cylinder,head,sector geometry: %d,%d,%d. "
1392 "Each cylinder is %s.\n"),
1393 chs->cylinders, chs->heads, chs->sectors, cyl_size);
1399 if (!opt_machine_mode) {
1400 printf (_("Partition Table: %s\n"), disk->type->name);
1404 has_extended = ped_disk_type_check_feature (disk->type,
1405 PED_DISK_TYPE_EXTENDED);
1406 has_name = ped_disk_type_check_feature (disk->type,
1407 PED_DISK_TYPE_PARTITION_NAME);
1411 if (!opt_machine_mode) {
1414 if (ped_unit_get_default() == PED_UNIT_CHS) {
1415 row1 = str_list_create (_("Number"), _("Start"),
1418 row1 = str_list_create (_("Number"), _("Start"),
1419 _("End"), _("Size"), NULL);
1423 str_list_append (row1, _("Type"));
1425 str_list_append (row1, _("File system"));
1428 str_list_append (row1, _("Name"));
1430 str_list_append (row1, _("Flags"));
1433 table = table_new (str_list_length(row1));
1435 table_add_row_from_strlist (table, row1);
1437 for (part = ped_disk_next_partition (disk, NULL); part;
1438 part = ped_disk_next_partition (disk, part)) {
1440 if ((!has_free_arg && !ped_partition_is_active(part)) ||
1441 part->type & PED_PARTITION_METADATA)
1444 tmp = ped_malloc (4);
1447 sprintf (tmp, "%2d ", part->num);
1449 sprintf (tmp, "%2s ", "");
1451 StrList *row = str_list_create (tmp, NULL);
1453 start = ped_unit_format (*dev, part->geom.start);
1454 end = ped_unit_format_byte (
1456 (part->geom.end + 1) * (*dev)->sector_size - 1);
1457 size = ped_unit_format (*dev, part->geom.length);
1458 if (ped_unit_get_default() == PED_UNIT_CHS) {
1459 str_list_append (row, start);
1460 str_list_append (row, end);
1462 str_list_append (row, start);
1463 str_list_append (row, end);
1464 str_list_append (row, size);
1467 if (!(part->type & PED_PARTITION_FREESPACE)) {
1469 name = ped_partition_type_get_name (part->type);
1470 str_list_append (row, name);
1473 str_list_append (row, part->fs_type ?
1474 part->fs_type->name : "");
1477 name = ped_partition_get_name (part);
1478 str_list_append (row, name);
1481 flags = partition_print_flags (part);
1482 str_list_append (row, flags);
1486 str_list_append (row, "");
1487 str_list_append (row, _("Free Space"));
1489 str_list_append (row, "");
1490 str_list_append (row, "");
1493 //PED_ASSERT (row.cols == caption.cols)
1494 table_add_row_from_strlist (table, row);
1495 str_list_destroy (row);
1502 table_rendered = table_render (table);
1504 printf("%ls\n", table_rendered);
1506 printf("%s\n", table_rendered);
1508 free (table_rendered);
1509 table_destroy (table);
1510 str_list_destroy (row1);
1514 for (part = ped_disk_next_partition (disk, NULL); part;
1515 part = ped_disk_next_partition (disk, part)) {
1517 if ((!has_free_arg && !ped_partition_is_active(part)) ||
1518 part->type & PED_PARTITION_METADATA)
1522 printf ("%d:", part->num);
1524 fputs ("1:", stdout);
1526 char *s = ped_unit_format (*dev, part->geom.start);
1529 s = ped_unit_format_byte (*dev,
1530 (part->geom.end + 1) *
1531 (*dev)->sector_size - 1);
1535 if (ped_unit_get_default() != PED_UNIT_CHS) {
1536 s = ped_unit_format (*dev, part->geom.length);
1541 if (!(part->type & PED_PARTITION_FREESPACE)) {
1544 printf ("%s:", part->fs_type->name);
1549 printf ("%s:", _(ped_partition_get_name (part)));
1553 printf ("%s;\n", partition_print_flags (part));
1561 ped_disk_destroy (disk);
1565 ped_disk_destroy (disk);
1573 PedDevice *current_dev = NULL;
1575 ped_device_probe_all();
1577 while ((current_dev = ped_device_get_next(current_dev))) {
1578 do_print (¤t_dev);
1586 do_quit (PedDevice** dev)
1592 static PedPartitionType
1593 _disk_get_part_type_for_sector (PedDisk* disk, PedSector sector)
1595 PedPartition* extended;
1597 extended = ped_disk_extended_partition (disk);
1599 || !ped_geometry_test_sector_inside (&extended->geom, sector))
1602 return PED_PARTITION_LOGICAL;
1605 /* This function checks if "part" contains a file system, and returs
1606 * 0 if either no file system was found, or the user declined to add it.
1607 * 1 if a file system was found, and the user chose to add it.
1608 * -1 if the user chose to cancel the entire search.
1611 _rescue_add_partition (PedPartition* part)
1613 const PedFileSystemType* fs_type;
1614 PedGeometry* probed;
1615 PedExceptionOption ex_opt;
1616 PedConstraint* constraint;
1620 fs_type = ped_file_system_probe (&part->geom);
1623 probed = ped_file_system_probe_specific (fs_type, &part->geom);
1627 if (!ped_geometry_test_inside (&part->geom, probed)) {
1628 ped_geometry_destroy (probed);
1632 constraint = ped_constraint_exact (probed);
1633 if (!ped_disk_set_partition_geom (part->disk, part, constraint,
1634 probed->start, probed->end)) {
1635 ped_constraint_destroy (constraint);
1638 ped_constraint_destroy (constraint);
1640 found_start = ped_unit_format (probed->dev, probed->start);
1641 found_end = ped_unit_format (probed->dev, probed->end);
1642 ex_opt = ped_exception_throw (
1643 PED_EXCEPTION_INFORMATION,
1644 PED_EXCEPTION_YES_NO_CANCEL,
1645 _("A %s %s partition was found at %s -> %s. "
1646 "Do you want to add it to the partition table?"),
1647 fs_type->name, ped_partition_type_get_name (part->type),
1648 found_start, found_end);
1649 ped_geometry_destroy (probed);
1654 case PED_EXCEPTION_CANCEL: return -1;
1655 case PED_EXCEPTION_NO: return 0;
1659 ped_partition_set_system (part, fs_type);
1660 ped_disk_commit (part->disk);
1664 /* hack: we only iterate through the start, since most (all) fs's have their
1665 * superblocks at the start. We'll need to change this if we generalize
1666 * for RAID, or something...
1669 _rescue_pass (PedDisk* disk, PedGeometry* start_range, PedGeometry* end_range)
1672 PedGeometry start_geom_exact;
1673 PedGeometry entire_dev;
1674 PedConstraint constraint;
1676 PedPartitionType part_type;
1678 part_type = _disk_get_part_type_for_sector (
1679 disk, (start_range->start + end_range->end) / 2);
1681 ped_geometry_init (&entire_dev, disk->dev, 0, disk->dev->length);
1683 ped_timer_reset (g_timer);
1684 ped_timer_set_state_name (g_timer, _("searching for file systems"));
1685 for (start = start_range->start; start <= start_range->end; start++) {
1686 ped_timer_update (g_timer, 1.0 * (start - start_range->start)
1687 / start_range->length);
1689 ped_geometry_init (&start_geom_exact, disk->dev, start, 1);
1690 ped_constraint_init (
1691 &constraint, ped_alignment_any, ped_alignment_any,
1692 &start_geom_exact, &entire_dev,
1693 1, disk->dev->length);
1694 part = ped_partition_new (disk, part_type, NULL, start,
1697 ped_constraint_done (&constraint);
1701 ped_exception_fetch_all ();
1702 if (ped_disk_add_partition (disk, part, &constraint)) {
1703 ped_exception_leave_all ();
1704 switch (_rescue_add_partition (part)) {
1706 ped_constraint_done (&constraint);
1710 ped_disk_remove_partition (disk, part);
1714 goto error_remove_partition;
1717 ped_exception_leave_all ();
1719 ped_partition_destroy (part);
1720 ped_constraint_done (&constraint);
1722 ped_timer_update (g_timer, 1.0);
1726 error_remove_partition:
1727 ped_disk_remove_partition (disk, part);
1728 ped_partition_destroy (part);
1729 ped_constraint_done (&constraint);
1734 do_rescue (PedDevice** dev)
1737 PedSector start = 0, end = 0;
1739 PedGeometry probe_start_region;
1740 PedGeometry probe_end_region;
1742 disk = ped_disk_new (*dev);
1746 if (!command_line_get_sector (_("Start?"), *dev, &start, NULL))
1747 goto error_destroy_disk;
1748 if (!command_line_get_sector (_("End?"), *dev, &end, NULL))
1749 goto error_destroy_disk;
1751 fuzz = PED_MAX (PED_MIN ((end - start) / 10, MEGABYTE_SECTORS(*dev)),
1752 MEGABYTE_SECTORS(*dev) * 16);
1754 ped_geometry_init (&probe_start_region, *dev,
1755 PED_MAX(start - fuzz, 0),
1756 PED_MIN(2 * fuzz, (*dev)->length - (start - fuzz)));
1757 ped_geometry_init (&probe_end_region, *dev,
1758 PED_MAX(end - fuzz, 0),
1759 PED_MIN(2 * fuzz, (*dev)->length - (end - fuzz)));
1761 if (!_rescue_pass (disk, &probe_start_region, &probe_end_region))
1762 goto error_destroy_disk;
1764 ped_disk_destroy (disk);
1766 if ((*dev)->type != PED_DEVICE_FILE)
1767 disk_is_modified = 1;
1772 ped_disk_destroy (disk);
1778 do_resize (PedDevice** dev)
1781 PedPartition *part = NULL;
1783 PedConstraint *constraint;
1784 PedSector start, end;
1785 PedGeometry *range_start = NULL, *range_end = NULL;
1786 PedGeometry new_geom;
1788 disk = ped_disk_new (*dev);
1792 if (!command_line_get_partition (_("Partition number?"), disk, &part))
1793 goto error_destroy_disk;
1794 if (part->type != PED_PARTITION_EXTENDED) {
1795 if (!_partition_warn_busy (part))
1796 goto error_destroy_disk;
1799 start = part->geom.start;
1800 end = part->geom.end;
1801 if (!command_line_get_sector (_("Start?"), *dev, &start, &range_start))
1802 goto error_destroy_disk;
1803 if (!command_line_get_sector (_("End?"), *dev, &end, &range_end))
1804 goto error_destroy_disk;
1806 if (!ped_geometry_init (&new_geom, *dev, start, end - start + 1))
1807 goto error_destroy_disk;
1808 snap_to_boundaries (&new_geom, &part->geom, disk,
1809 range_start, range_end);
1811 if (part->type == PED_PARTITION_EXTENDED) {
1812 constraint = constraint_from_start_end (*dev,
1813 range_start, range_end);
1814 if (!ped_disk_set_partition_geom (disk, part, constraint,
1815 new_geom.start, new_geom.end))
1816 goto error_destroy_constraint;
1817 ped_partition_set_system (part, NULL);
1819 fs = ped_file_system_open (&part->geom);
1821 goto error_destroy_disk;
1822 constraint = constraint_intersect_and_destroy (
1823 ped_file_system_get_resize_constraint (fs),
1824 constraint_from_start_end (
1825 *dev, range_start, range_end));
1826 if (!ped_disk_set_partition_geom (disk, part, constraint,
1827 new_geom.start, new_geom.end))
1828 goto error_close_fs;
1829 if (!ped_file_system_resize (fs, &part->geom, g_timer))
1830 goto error_close_fs;
1831 /* may have changed... eg fat16 -> fat32 */
1832 ped_partition_set_system (part, fs->type);
1833 ped_file_system_close (fs);
1836 ped_disk_commit (disk);
1837 ped_constraint_destroy (constraint);
1838 ped_disk_destroy (disk);
1839 if (range_start != NULL)
1840 ped_geometry_destroy (range_start);
1841 if (range_end != NULL)
1842 ped_geometry_destroy (range_end);
1844 if ((*dev)->type != PED_DEVICE_FILE)
1845 disk_is_modified = 1;
1850 ped_file_system_close (fs);
1851 error_destroy_constraint:
1852 ped_constraint_destroy (constraint);
1854 ped_disk_destroy (disk);
1856 if (range_start != NULL)
1857 ped_geometry_destroy (range_start);
1858 if (range_end != NULL)
1859 ped_geometry_destroy (range_end);
1864 do_rm (PedDevice** dev)
1867 PedPartition* part = NULL;
1869 disk = ped_disk_new (*dev);
1873 if (!command_line_get_partition (_("Partition number?"), disk, &part))
1874 goto error_destroy_disk;
1875 if (!_partition_warn_busy (part))
1876 goto error_destroy_disk;
1878 ped_disk_delete_partition (disk, part);
1879 ped_disk_commit (disk);
1880 ped_disk_destroy (disk);
1882 if ((*dev)->type != PED_DEVICE_FILE)
1883 disk_is_modified = 1;
1888 ped_disk_destroy (disk);
1894 do_select (PedDevice** dev)
1896 PedDevice* new_dev = *dev;
1898 if (!command_line_get_device (_("New device?"), &new_dev))
1900 if (!ped_device_open (new_dev))
1903 ped_device_close (*dev);
1905 print_using_dev (*dev);
1910 do_set (PedDevice** dev)
1913 PedPartition* part = NULL;
1914 PedPartitionFlag flag;
1917 disk = ped_disk_new (*dev);
1921 if (!command_line_get_partition (_("Partition number?"), disk, &part))
1922 goto error_destroy_disk;
1923 if (!command_line_get_part_flag (_("Flag to Invert?"), part, &flag))
1924 goto error_destroy_disk;
1925 state = (ped_partition_get_flag (part, flag) == 0 ? 1 : 0);
1927 if (!is_toggle_mode) {
1928 if (!command_line_get_state (_("New state?"), &state))
1929 goto error_destroy_disk;
1932 if (!ped_partition_set_flag (part, flag, state))
1933 goto error_destroy_disk;
1934 if (!ped_disk_commit (disk))
1935 goto error_destroy_disk;
1936 ped_disk_destroy (disk);
1938 if ((*dev)->type != PED_DEVICE_FILE)
1939 disk_is_modified = 1;
1944 ped_disk_destroy (disk);
1950 do_toggle (PedDevice **dev)
1955 result = do_set (dev);
1962 do_unit (PedDevice** dev)
1964 PedUnit unit = ped_unit_get_default ();
1965 if (!command_line_get_unit (_("Unit?"), &unit))
1967 ped_unit_set_default (unit);
1985 PedFileSystemType* fs_type;
1986 PedDiskType* disk_type;
1987 PedPartitionFlag part_flag;
1992 list = str_list_create (_(flag_msg_start), NULL);
1993 for (part_flag = ped_partition_flag_next (0); part_flag;
1994 part_flag = ped_partition_flag_next (part_flag)) {
1998 str_list_append (list, ", ");
1999 str_list_append (list,
2000 _(ped_partition_flag_get_name (part_flag)));
2002 str_list_append (list, "\n");
2004 flag_msg = str_list_convert (list);
2005 str_list_destroy (list);
2009 list = str_list_create (_(unit_msg_start), NULL);
2010 for (unit = PED_UNIT_FIRST; unit <= PED_UNIT_LAST; unit++) {
2014 str_list_append (list, ", ");
2015 str_list_append (list, ped_unit_get_name (unit));
2017 str_list_append (list, "\n");
2019 unit_msg = str_list_convert (list);
2020 str_list_destroy (list);
2023 list = str_list_create (_(label_type_msg_start), NULL);
2026 for (disk_type = ped_disk_type_get_next (NULL);
2027 disk_type; disk_type = ped_disk_type_get_next (disk_type)) {
2028 if (disk_type->ops->write == NULL)
2034 str_list_append (list, ", ");
2035 str_list_append (list, disk_type->name);
2037 str_list_append (list, "\n");
2039 label_type_msg = str_list_convert (list);
2040 str_list_destroy (list);
2042 /* mkfs - file system types */
2043 list = str_list_create (_(fs_type_msg_start), NULL);
2046 for (fs_type = ped_file_system_type_get_next (NULL);
2047 fs_type; fs_type = ped_file_system_type_get_next (fs_type)) {
2048 if (fs_type->ops->create == NULL)
2054 str_list_append (list, ", ");
2055 str_list_append (list, fs_type->name);
2057 str_list_append (list, "\n");
2059 mkfs_fs_type_msg = str_list_convert (list);
2060 str_list_destroy (list);
2062 /* mkpart - file system types */
2063 list = str_list_create (_(fs_type_msg_start), NULL);
2066 for (fs_type = ped_file_system_type_get_next (NULL);
2067 fs_type; fs_type = ped_file_system_type_get_next (fs_type)) {
2071 str_list_append (list, ", ");
2072 str_list_append (list, fs_type->name);
2074 str_list_append (list, "\n");
2076 mkpart_fs_type_msg = str_list_convert (list);
2077 str_list_destroy (list);
2079 /* resize - file system types */
2080 list = str_list_create (_(resize_msg_start), NULL);
2083 for (fs_type = ped_file_system_type_get_next (NULL);
2084 fs_type; fs_type = ped_file_system_type_get_next (fs_type)) {
2085 if (fs_type->ops->resize == NULL)
2091 str_list_append (list, ", ");
2092 str_list_append (list, fs_type->name);
2094 str_list_append (list, "\n");
2096 resize_fs_type_msg = str_list_convert (list);
2097 str_list_destroy (list);
2104 free (mkfs_fs_type_msg);
2105 free (mkpart_fs_type_msg);
2106 free (resize_fs_type_msg);
2107 free (label_type_msg);
2113 command_register (commands, command_create (
2114 str_list_create_unique ("check", _("check"), NULL),
2117 _("check NUMBER do a simple check on the file "
2120 str_list_create (_(number_msg), NULL), 1));
2122 command_register (commands, command_create (
2123 str_list_create_unique ("cp", _("cp"), NULL),
2126 _("cp [FROM-DEVICE] FROM-NUMBER TO-NUMBER copy file system to another "
2129 str_list_create (_(number_msg), _(device_msg), NULL), 1));
2131 command_register (commands, command_create (
2132 str_list_create_unique ("help", _("help"), NULL),
2135 _("help [COMMAND] print general help, or help "
2140 command_register (commands, command_create (
2141 str_list_create_unique ("mklabel", _("mklabel"), "mktable", _("mktable"), NULL),
2144 _("mklabel,mktable LABEL-TYPE create a new disklabel "
2145 "(partition table)"),
2147 str_list_create (label_type_msg, NULL), 1));
2149 command_register (commands, command_create (
2150 str_list_create_unique ("mkfs", _("mkfs"), NULL),
2153 _("mkfs NUMBER FS-TYPE make a FS-TYPE file "
2154 "system on partititon NUMBER"),
2156 str_list_create (_(number_msg), _(mkfs_fs_type_msg), NULL), 1));
2158 command_register (commands, command_create (
2159 str_list_create_unique ("mkpart", _("mkpart"), NULL),
2162 _("mkpart PART-TYPE [FS-TYPE] START END make a partition"),
2164 str_list_create (_(part_type_msg),
2165 _(mkpart_fs_type_msg),
2168 _("'mkpart' makes a partition without creating a new file system on the "
2169 "partition. FS-TYPE may be specified to set an appropriate partition ID.\n"),
2172 command_register (commands, command_create (
2173 str_list_create_unique ("mkpartfs", _("mkpartfs"), NULL),
2176 _("mkpartfs PART-TYPE FS-TYPE START END make a partition with a "
2179 str_list_create (_(part_type_msg), _(start_end_msg), NULL), 1));
2181 command_register (commands, command_create (
2182 str_list_create_unique ("move", _("move"), NULL),
2185 _("move NUMBER START END move partition NUMBER"),
2187 str_list_create (_(number_msg), _(start_end_msg), NULL), 1));
2189 command_register (commands, command_create (
2190 str_list_create_unique ("name", _("name"), NULL),
2193 _("name NUMBER NAME name partition NUMBER as NAME"),
2195 str_list_create (_(number_msg), _(name_msg), NULL), 1));
2197 command_register (commands, command_create (
2198 str_list_create_unique ("print", _("print"), NULL),
2201 _("print [devices|free|list,all|NUMBER] display the partition table, "
2202 "available devices, free space, all found partitions, or a particular "
2206 _("Without arguments, 'print' displays the entire partition table. However "
2207 "with the following arguments it performs various other actions.\n"),
2208 _(" devices : display all active block devices\n"),
2209 _(" free : display information about free unpartitioned space on the "
2210 "current block device\n"),
2211 _(" list, all : display the partition tables of all active block devices\n"),
2212 _(" NUMBER : display more detailed information about this particular "
2216 command_register (commands, command_create (
2217 str_list_create_unique ("quit", _("quit"), NULL),
2220 _("quit exit program"),
2224 command_register (commands, command_create (
2225 str_list_create_unique ("rescue", _("rescue"), NULL),
2228 _("rescue START END rescue a lost partition near "
2231 str_list_create (_(start_end_msg), NULL), 1));
2233 command_register (commands, command_create (
2234 str_list_create_unique ("resize", _("resize"), NULL),
2237 _("resize NUMBER START END resize partition NUMBER and "
2240 str_list_create (_(number_msg),
2242 _(resize_fs_type_msg), NULL), 1));
2244 command_register (commands, command_create (
2245 str_list_create_unique ("rm", _("rm"), NULL),
2248 _("rm NUMBER delete partition NUMBER"),
2250 str_list_create (_(number_msg), NULL), 1));
2252 command_register (commands, command_create (
2253 str_list_create_unique ("select", _("select"), NULL),
2256 _("select DEVICE choose the device to edit"),
2258 str_list_create (_(device_msg), NULL), 1));
2260 command_register (commands, command_create (
2261 str_list_create_unique ("set", _("set"), NULL),
2264 _("set NUMBER FLAG STATE change the FLAG on partition "
2267 str_list_create (_(number_msg), flag_msg, _(state_msg), NULL), 1));
2269 command_register (commands, command_create (
2270 str_list_create_unique ("toggle", _("toggle"), NULL),
2273 _("toggle [NUMBER [FLAG]] toggle the state of FLAG on "
2274 "partition NUMBER"),
2276 str_list_create (_(number_msg), flag_msg, NULL), 1));
2278 command_register (commands, command_create (
2279 str_list_create_unique ("unit", _("unit"), NULL),
2282 _("unit UNIT set the default unit to UNIT"),
2284 str_list_create (unit_msg, NULL), 1));
2286 command_register (commands, command_create (
2287 str_list_create_unique ("version", _("version"), NULL),
2290 _("version display the version number "
2291 "and copyright information of GNU Parted"),
2294 _("'version' displays copyright and version information corresponding to this "
2295 "copy of GNU Parted\n"),
2305 for (walk = commands; *walk; walk++) {
2306 command_destroy (*walk);
2314 /* intialize i18n */
2316 setlocale(LC_ALL, "");
2317 bindtextdomain(PACKAGE, LOCALEDIR);
2318 textdomain(PACKAGE);
2319 #endif /* ENABLE_NLS */
2325 version_etc (stdout, PROGRAM_NAME, PACKAGE_NAME, VERSION, AUTHORS,
2330 _parse_options (int* argc_ptr, char*** argv_ptr)
2332 int opt, help = 0, list = 0, version = 0, wrong = 0;
2336 opt = getopt_long (*argc_ptr, *argv_ptr, "hlmsv",
2342 case 'h': help = 1; break;
2343 case 'l': list = 1; break;
2344 case 'm': opt_machine_mode = 1; break;
2345 case 's': opt_script_mode = 1; break;
2346 case 'v': version = 1; break;
2347 case PRETEND_INPUT_TTY:
2348 pretend_input_tty = 1;
2350 default: wrong = 1; break;
2356 _("Usage: %s [-hlmsv] [DEVICE [COMMAND [PARAMETERS]]...]\n"),
2363 exit (EXIT_SUCCESS);
2368 exit (EXIT_SUCCESS);
2373 exit (EXIT_SUCCESS);
2376 *argc_ptr -= optind;
2377 *argv_ptr += optind;
2382 _choose_device (int* argc_ptr, char*** argv_ptr)
2386 /* specified on comand line? */
2388 dev = ped_device_get ((*argv_ptr) [0]);
2395 ped_device_probe_all ();
2396 dev = ped_device_get_next (NULL);
2398 if (ped_exception_throw (PED_EXCEPTION_ERROR,
2399 PED_EXCEPTION_RETRY_CANCEL,
2400 _("No device found"))
2401 == PED_EXCEPTION_RETRY)
2408 if (!ped_device_open (dev))
2414 _init (int* argc_ptr, char*** argv_ptr)
2418 #ifdef ENABLE_MTRACE
2428 if (!_parse_options (argc_ptr, argv_ptr))
2429 goto error_done_commands;
2432 if (getuid() != 0 && !opt_script_mode) {
2433 puts (_("WARNING: You are not superuser. Watch out for "
2438 dev = _choose_device (argc_ptr, argv_ptr);
2440 goto error_done_commands;
2442 g_timer = ped_timer_new (_timer_handler, &timer_context);
2444 goto error_done_commands;
2445 timer_context.last_update = 0;
2449 error_done_commands:
2458 _done (PedDevice* dev)
2460 if (dev->boot_dirty && dev->type != PED_DEVICE_FILE) {
2461 ped_exception_throw (
2462 PED_EXCEPTION_WARNING,
2464 _("You should reinstall your boot loader before "
2465 "rebooting. Read section 4 of the Parted User "
2466 "documentation for more information."));
2468 if (!opt_script_mode && !opt_machine_mode && disk_is_modified) {
2469 ped_exception_throw (
2470 PED_EXCEPTION_INFORMATION, PED_EXCEPTION_OK,
2471 _("You may need to update /etc/fstab.\n"));
2474 ped_device_close (dev);
2476 ped_timer_destroy (g_timer);
2483 main (int argc, char** argv)
2488 set_program_name (argv[0]);
2489 atexit (close_stdout);
2491 dev = _init (&argc, &argv);
2495 if (argc || opt_script_mode)
2496 status = non_interactive_mode (&dev, commands, argc, argv);
2498 status = interactive_mode (&dev, commands);