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/>.
22 #include "configmake.h"
23 #include "version-etc.h"
29 "<http://parted.alioth.debian.org/cgi-bin/trac.cgi/browser/AUTHORS>"
31 /* The official name of this program (e.g., no `g' prefix). */
32 #define PROGRAM_NAME "parted"
34 #define N_(String) String
38 # define _(String) dgettext (PACKAGE, String)
40 # define _(String) (String)
41 #endif /* ENABLE_NLS */
43 #include <parted/parted.h>
44 #include <parted/debug.h>
60 /* minimum amount of free space to leave, or maximum amount to gobble up */
61 #define MIN_FREESPACE (1000 * 2) /* 1000k */
63 static int MEGABYTE_SECTORS (PedDevice* dev)
65 return PED_MEGABYTE_SIZE / dev->sector_size;
68 /* For long options that have no equivalent short option, use a
69 non-character as a pseudo short option, starting with CHAR_MAX + 1. */
72 PRETEND_INPUT_TTY = CHAR_MAX + 1,
78 time_t predicted_time_left;
81 static struct option options[] = {
82 /* name, has-arg, string-return-val, char-return-val */
83 {"help", 0, NULL, 'h'},
84 {"list", 0, NULL, 'l'},
85 {"machine", 0, NULL, 'm'},
86 {"script", 0, NULL, 's'},
87 {"version", 0, NULL, 'v'},
88 {"-pretend-input-tty", 0, NULL, PRETEND_INPUT_TTY},
92 static char* options_help [][2] = {
93 {"help", N_("displays this help message")},
94 {"list", N_("lists partition layout on all block devices")},
95 {"machine", N_("displays machine parseable output")},
96 {"script", N_("never prompts for user intervention")},
97 {"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 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 char* label_type_msg_start = N_("LABEL-TYPE is one of: ");
114 static char* flag_msg_start = N_("FLAG is one of: ");
115 static char* unit_msg_start = N_("UNIT is one of: ");
116 static char* part_type_msg = N_("PART-TYPE is one of: primary, logical, "
118 static char* fs_type_msg_start = N_("FS-TYPE is one of: ");
119 static 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 char* state_msg = N_("STATE is one of: on, off\n");
123 static char* device_msg = N_("DEVICE is usually /dev/hda or /dev/sda\n");
124 static char* name_msg = N_("NAME is any word you want\n");
125 static char* resize_msg_start = N_("The partition must have one of the "
126 "following FS-TYPEs: ");
128 static 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;
737 ped_free (peek_word);
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 if (!final_constraint)
762 goto error_destroy_simple_constraints;
764 /* subject to partition constraint */
765 ped_exception_fetch_all();
766 if (!ped_disk_add_partition (disk, part, final_constraint)) {
767 ped_exception_leave_all();
769 if (ped_disk_add_partition (disk, part,
770 ped_constraint_any (*dev))) {
771 start_usr = ped_unit_format (*dev, start);
772 end_usr = ped_unit_format (*dev, end);
773 start_sol = ped_unit_format (*dev, part->geom.start);
774 end_sol = ped_unit_format (*dev, part->geom.end);
776 switch (ped_exception_throw (
777 PED_EXCEPTION_WARNING,
778 PED_EXCEPTION_YES_NO,
779 _("You requested a partition from %s to %s.\n"
780 "The closest location we can manage is "
782 "Is this still acceptable to you?"),
783 start_usr, end_usr, start_sol, end_sol))
785 case PED_EXCEPTION_YES:
786 /* all is well in this state */
788 case PED_EXCEPTION_NO:
789 case PED_EXCEPTION_UNHANDLED:
791 /* undo partition addition */
792 goto error_remove_part;
795 goto error_remove_part;
798 ped_exception_leave_all();
800 ped_exception_catch();
802 /* set minor attributes */
804 PED_ASSERT (ped_partition_set_name (part, part_name), return 0);
805 if (!ped_partition_set_system (part, fs_type))
806 goto error_destroy_disk;
807 if (ped_partition_is_flag_available (part, PED_PARTITION_LBA))
808 ped_partition_set_flag (part, PED_PARTITION_LBA, 1);
810 if (!ped_disk_commit (disk))
811 goto error_destroy_disk;
814 ped_constraint_destroy (final_constraint);
815 ped_constraint_destroy (user_constraint);
816 ped_constraint_destroy (dev_constraint);
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);
825 if (start_usr != NULL)
826 ped_free (start_usr);
829 if (start_sol != NULL)
830 ped_free (start_sol);
834 if ((*dev)->type != PED_DEVICE_FILE)
835 disk_is_modified = 1;
840 ped_disk_remove_partition (disk, part);
841 ped_constraint_destroy (final_constraint);
842 error_destroy_simple_constraints:
843 ped_constraint_destroy (user_constraint);
844 ped_constraint_destroy (dev_constraint);
845 ped_partition_destroy (part);
847 ped_disk_destroy (disk);
849 if (range_start != NULL)
850 ped_geometry_destroy (range_start);
851 if (range_end != NULL)
852 ped_geometry_destroy (range_end);
854 if (start_usr != NULL)
855 ped_free (start_usr);
858 if (start_sol != NULL)
859 ped_free (start_sol);
867 do_mkpartfs (PedDevice** dev)
871 PedPartitionType part_type;
872 const PedFileSystemType* fs_type = ped_file_system_type_get ("ext2");
873 PedSector start = 0, end = 0;
874 PedGeometry *range_start = NULL, *range_end = NULL;
875 PedConstraint* user_constraint;
876 PedConstraint* dev_constraint;
877 PedConstraint* final_constraint;
879 char* part_name = NULL;
880 char *start_usr = NULL, *end_usr = NULL;
881 char *start_sol = NULL, *end_sol = NULL;
883 disk = ped_disk_new (*dev);
887 if (!ped_disk_type_check_feature (disk->type, PED_DISK_TYPE_EXTENDED)) {
888 part_type = PED_PARTITION_NORMAL;
890 if (!command_line_get_part_type (_("Partition type?"),
892 goto error_destroy_disk;
895 if (ped_disk_type_check_feature (disk->type,
896 PED_DISK_TYPE_PARTITION_NAME))
897 part_name = command_line_get_word (_("Partition name?"),
900 if (part_type == PED_PARTITION_EXTENDED) {
901 ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
902 _("An extended partition cannot hold a file system. "
903 "Did you want mkpart?"));
904 goto error_destroy_disk;
907 if (!command_line_get_fs_type (_("File system type?"), &fs_type))
908 goto error_destroy_disk;
909 if (!command_line_get_sector (_("Start?"), *dev, &start,
911 goto error_destroy_disk;
912 if (!command_line_get_sector (_("End?"), *dev, &end, &range_end))
913 goto error_destroy_disk;
915 /* attempt to create the partition now */
916 part = ped_partition_new (disk, part_type, fs_type, start, end);
918 goto error_destroy_disk;
920 snap_to_boundaries (&part->geom, NULL, disk, range_start, range_end);
922 /* create constraints */
923 user_constraint = constraint_from_start_end (*dev, range_start,
925 PED_ASSERT (user_constraint != NULL, return 0);
927 dev_constraint = ped_device_get_constraint (*dev);
928 PED_ASSERT (dev_constraint != NULL, return 0);
930 final_constraint = ped_constraint_intersect (user_constraint,
932 if (!final_constraint)
933 goto error_destroy_simple_constraints;
935 /* subject to partition constraint */
936 ped_exception_fetch_all();
937 if (!ped_disk_add_partition (disk, part, final_constraint)) {
938 ped_exception_leave_all();
940 if (ped_disk_add_partition (disk, part,
941 ped_constraint_any (*dev))) {
942 start_usr = ped_unit_format (*dev, start);
943 end_usr = ped_unit_format (*dev, end);
944 start_sol = ped_unit_format (*dev, part->geom.start);
945 end_sol = ped_unit_format (*dev, part->geom.end);
947 switch (ped_exception_throw (
948 PED_EXCEPTION_WARNING,
949 PED_EXCEPTION_YES_NO,
950 _("You requested a partition from %s to %s.\n"
951 "The closest location we can manage is "
953 "Is this still acceptable to you?"),
954 start_usr, end_usr, start_sol, end_sol)) {
955 case PED_EXCEPTION_YES:
956 /* all is well in this state */
958 case PED_EXCEPTION_NO:
959 case PED_EXCEPTION_UNHANDLED:
961 /* undo partition addition */
962 goto error_remove_part;
965 goto error_remove_part;
968 ped_exception_leave_all();
970 ped_exception_catch();
972 /* set LBA flag automatically if available */
973 if (ped_partition_is_flag_available (part, PED_PARTITION_LBA))
974 ped_partition_set_flag (part, PED_PARTITION_LBA, 1);
977 fs = ped_file_system_create (&part->geom, fs_type, g_timer);
979 goto error_destroy_disk;
980 ped_file_system_close (fs);
982 if (!ped_partition_set_system (part, fs_type))
983 goto error_destroy_disk;
985 if (!ped_disk_commit (disk))
986 goto error_destroy_disk;
989 ped_constraint_destroy (final_constraint);
990 ped_constraint_destroy (user_constraint);
991 ped_constraint_destroy (dev_constraint);
993 ped_disk_destroy (disk);
995 if (range_start != NULL)
996 ped_geometry_destroy (range_start);
997 if (range_end != NULL)
998 ped_geometry_destroy (range_end);
1000 if (start_usr != NULL)
1001 ped_free (start_usr);
1002 if (end_usr != NULL)
1004 if (start_sol != NULL)
1005 ped_free (start_sol);
1006 if (end_sol != NULL)
1009 if ((*dev)->type != PED_DEVICE_FILE)
1010 disk_is_modified = 1;
1015 ped_disk_remove_partition (disk, part);
1016 ped_constraint_destroy (final_constraint);
1017 error_destroy_simple_constraints:
1018 ped_constraint_destroy (user_constraint);
1019 ped_constraint_destroy (dev_constraint);
1020 ped_partition_destroy (part);
1022 ped_disk_destroy (disk);
1024 if (range_start != NULL)
1025 ped_geometry_destroy (range_start);
1026 if (range_end != NULL)
1027 ped_geometry_destroy (range_end);
1029 if (start_usr != NULL)
1030 ped_free (start_usr);
1031 if (end_usr != NULL)
1033 if (start_sol != NULL)
1034 ped_free (start_sol);
1035 if (end_sol != NULL)
1042 do_move (PedDevice** dev)
1045 PedPartition* part = NULL;
1047 PedFileSystem* fs_copy;
1048 PedConstraint* constraint;
1049 PedSector start = 0, end = 0;
1050 PedGeometry *range_start = NULL, *range_end = NULL;
1051 PedGeometry old_geom, new_geom;
1053 disk = ped_disk_new (*dev);
1057 if (!command_line_get_partition (_("Partition number?"), disk, &part))
1058 goto error_destroy_disk;
1059 if (!_partition_warn_busy (part))
1060 goto error_destroy_disk;
1061 if (part->type == PED_PARTITION_EXTENDED) {
1062 ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
1063 _("Can't move an extended partition."));
1064 goto error_destroy_disk;
1066 old_geom = part->geom;
1067 fs = ped_file_system_open (&old_geom);
1069 goto error_destroy_disk;
1071 /* get new target */
1072 if (!command_line_get_sector (_("Start?"), *dev, &start, &range_start))
1073 goto error_close_fs;
1074 end = start + old_geom.length - 1;
1075 if (!command_line_get_sector (_("End?"), *dev, &end, &range_end))
1076 goto error_close_fs;
1078 /* set / test on "disk" */
1079 if (!ped_geometry_init (&new_geom, *dev, start, end - start + 1))
1080 goto error_close_fs;
1081 snap_to_boundaries (&new_geom, NULL, disk, range_start, range_end);
1083 constraint = constraint_intersect_and_destroy (
1084 ped_file_system_get_copy_constraint (fs, *dev),
1085 constraint_from_start_end(*dev,range_start,range_end));
1086 if (!ped_disk_set_partition_geom (disk, part, constraint,
1087 new_geom.start, new_geom.end))
1088 goto error_destroy_constraint;
1089 ped_constraint_destroy (constraint);
1090 if (ped_geometry_test_overlap (&old_geom, &part->geom)) {
1091 ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
1092 _("Can't move a partition onto itself. Try using "
1093 "resize, perhaps?"));
1094 goto error_close_fs;
1098 fs_copy = ped_file_system_copy (fs, &part->geom, g_timer);
1100 goto error_close_fs;
1101 ped_file_system_close (fs_copy);
1102 ped_file_system_close (fs);
1103 if (!ped_disk_commit (disk))
1104 goto error_destroy_disk;
1105 ped_disk_destroy (disk);
1106 if (range_start != NULL)
1107 ped_geometry_destroy (range_start);
1108 if (range_end != NULL)
1109 ped_geometry_destroy (range_end);
1111 if ((*dev)->type != PED_DEVICE_FILE)
1112 disk_is_modified = 1;
1116 error_destroy_constraint:
1117 ped_constraint_destroy (constraint);
1119 ped_file_system_close (fs);
1121 ped_disk_destroy (disk);
1123 if (range_start != NULL)
1124 ped_geometry_destroy (range_start);
1125 if (range_end != NULL)
1126 ped_geometry_destroy (range_end);
1131 do_name (PedDevice** dev)
1134 PedPartition* part = NULL;
1137 disk = ped_disk_new (*dev);
1141 if (!command_line_get_partition (_("Partition number?"), disk, &part))
1142 goto error_destroy_disk;
1144 name = command_line_get_word (_("Partition name?"),
1145 ped_partition_get_name (part), NULL, 0);
1147 goto error_destroy_disk;
1148 if (!ped_partition_set_name (part, name))
1149 goto error_free_name;
1152 if (!ped_disk_commit (disk))
1153 goto error_destroy_disk;
1154 ped_disk_destroy (disk);
1160 ped_disk_destroy (disk);
1166 partition_print_flags (PedPartition* part)
1168 PedPartitionFlag flag;
1171 char* res = ped_malloc(1);
1177 for (flag = ped_partition_flag_next (0); flag;
1178 flag = ped_partition_flag_next (flag)) {
1179 if (ped_partition_get_flag (part, flag)) {
1184 ped_realloc (&_res, strlen (res)
1187 strncat (res, ", ", 2);
1190 name = _(ped_partition_flag_get_name (flag));
1192 ped_realloc (&_res, strlen (res) + 1
1195 strncat (res, name, 21);
1202 /* Prints a sector out, first in compact form, and then with a percentage.
1206 print_sector_compact_and_percent (PedSector sector, PedDevice* dev)
1211 if (ped_unit_get_default() == PED_UNIT_PERCENT)
1212 compact = ped_unit_format (dev, sector);
1214 compact = ped_unit_format_custom (dev, sector,
1217 percent = ped_unit_format_custom (dev, sector, PED_UNIT_PERCENT);
1219 printf ("%s (%s)\n", compact, percent);
1226 partition_print (PedPartition* part)
1229 PedConstraint* resize_constraint;
1232 fs = ped_file_system_open (&part->geom);
1238 flags = partition_print_flags (part);
1240 printf (_("Minor: %d\n"), part->num);
1241 printf (_("Flags: %s\n"), flags);
1242 printf (_("File System: %s\n"), fs->type->name);
1243 fputs (_("Size: "), stdout);
1244 print_sector_compact_and_percent (part->geom.length, part->geom.dev);
1246 resize_constraint = ped_file_system_get_resize_constraint (fs);
1247 if (resize_constraint) {
1248 fputs (_("Minimum size: "), stdout);
1249 print_sector_compact_and_percent (resize_constraint->min_size,
1251 fputs (_("Maximum size: "), stdout);
1252 print_sector_compact_and_percent (resize_constraint->max_size,
1254 ped_constraint_destroy (resize_constraint);
1260 ped_file_system_close (fs);
1266 do_print (PedDevice** dev)
1268 PedUnit default_unit;
1273 int has_devices_arg = 0;
1274 int has_free_arg = 0;
1275 int has_list_arg = 0;
1276 int has_num_arg = 0;
1277 char* transport[14] = {"unknown", "scsi", "ide", "dac960",
1278 "cpqarray", "file", "ataraid", "i2o",
1279 "ubd", "dasd", "viodasd", "sx8", "dm",
1288 wchar_t* table_rendered;
1290 disk = ped_disk_new (*dev);
1294 peek_word = command_line_peek_word ();
1296 if (strncmp (peek_word, "devices", 7) == 0) {
1297 command_line_pop_word();
1298 has_devices_arg = 1;
1300 else if (strncmp (peek_word, "free", 4) == 0) {
1301 command_line_pop_word ();
1304 else if (strncmp (peek_word, "list", 4) == 0 ||
1305 strncmp (peek_word, "all", 3) == 0) {
1306 command_line_pop_word();
1310 has_num_arg = isdigit(peek_word[0]);
1312 ped_free (peek_word);
1315 if (has_devices_arg) {
1317 PedDevice* current_dev = NULL;
1319 ped_device_probe_all();
1321 while ((current_dev = ped_device_get_next(current_dev))) {
1322 end = ped_unit_format_byte (current_dev,
1324 * current_dev->sector_size);
1325 printf ("%s (%s)\n", current_dev->path, end);
1329 dev_name = xstrdup ((*dev)->path);
1330 ped_device_free_all ();
1332 *dev = ped_device_get (dev_name);
1335 if (!ped_device_open (*dev))
1338 ped_free (dev_name);
1343 else if (has_list_arg)
1344 return _print_list ();
1346 else if (has_num_arg) {
1347 PedPartition* part = NULL;
1349 if (command_line_get_partition ("", disk, &part))
1350 status = partition_print (part);
1351 ped_disk_destroy (disk);
1355 start = ped_unit_format (*dev, 0);
1356 default_unit = ped_unit_get_default ();
1357 end = ped_unit_format_byte (*dev, (*dev)->length * (*dev)->sector_size
1358 - (default_unit == PED_UNIT_CHS ||
1359 default_unit == PED_UNIT_CYLINDER));
1361 if (opt_machine_mode) {
1362 switch (default_unit) {
1363 case PED_UNIT_CHS: puts ("CHS;");
1365 case PED_UNIT_CYLINDER: puts ("CYL;");
1367 default: puts ("BYT;");
1371 printf ("%s:%s:%s:%lld:%lld:%s:%s;\n",
1372 (*dev)->path, end, transport[(*dev)->type],
1373 (*dev)->sector_size, (*dev)->phys_sector_size,
1374 disk->type->name, (*dev)->model);
1376 printf (_("Model: %s (%s)\n"),
1377 (*dev)->model, transport[(*dev)->type]);
1378 printf (_("Disk %s: %s\n"), (*dev)->path, end);
1379 printf (_("Sector size (logical/physical): %lldB/%lldB\n"),
1380 (*dev)->sector_size, (*dev)->phys_sector_size);
1386 if (ped_unit_get_default () == PED_UNIT_CHS
1387 || ped_unit_get_default () == PED_UNIT_CYLINDER) {
1388 PedCHSGeometry* chs = &(*dev)->bios_geom;
1389 char* cyl_size = ped_unit_format_custom (*dev,
1390 chs->heads * chs->sectors,
1393 if (opt_machine_mode) {
1394 printf ("%d:%d:%d:%s;\n",
1395 chs->cylinders, chs->heads, chs->sectors, cyl_size);
1397 printf (_("BIOS cylinder,head,sector geometry: %d,%d,%d. "
1398 "Each cylinder is %s.\n"),
1399 chs->cylinders, chs->heads, chs->sectors, cyl_size);
1402 ped_free (cyl_size);
1405 if (!opt_machine_mode) {
1406 printf (_("Partition Table: %s\n"), disk->type->name);
1410 has_extended = ped_disk_type_check_feature (disk->type,
1411 PED_DISK_TYPE_EXTENDED);
1412 has_name = ped_disk_type_check_feature (disk->type,
1413 PED_DISK_TYPE_PARTITION_NAME);
1417 if (!opt_machine_mode) {
1420 if (ped_unit_get_default() == PED_UNIT_CHS) {
1421 row1 = str_list_create (_("Number"), _("Start"),
1424 row1 = str_list_create (_("Number"), _("Start"),
1425 _("End"), _("Size"), NULL);
1429 str_list_append (row1, _("Type"));
1431 str_list_append (row1, _("File system"));
1434 str_list_append (row1, _("Name"));
1436 str_list_append (row1, _("Flags"));
1439 table = table_new (str_list_length(row1));
1441 table_add_row_from_strlist (table, row1);
1443 for (part = ped_disk_next_partition (disk, NULL); part;
1444 part = ped_disk_next_partition (disk, part)) {
1446 if ((!has_free_arg && !ped_partition_is_active(part)) ||
1447 part->type & PED_PARTITION_METADATA)
1450 tmp = ped_malloc (4);
1453 sprintf (tmp, "%2d ", part->num);
1455 sprintf (tmp, "%2s ", "");
1457 StrList *row = str_list_create (tmp, NULL);
1459 start = ped_unit_format (*dev, part->geom.start);
1460 end = ped_unit_format_byte (
1462 (part->geom.end + 1) * (*dev)->sector_size - 1);
1463 size = ped_unit_format (*dev, part->geom.length);
1464 if (ped_unit_get_default() == PED_UNIT_CHS) {
1465 str_list_append (row, start);
1466 str_list_append (row, end);
1468 str_list_append (row, start);
1469 str_list_append (row, end);
1470 str_list_append (row, size);
1473 if (!(part->type & PED_PARTITION_FREESPACE)) {
1475 name = ped_partition_type_get_name (part->type);
1476 str_list_append (row, name);
1479 str_list_append (row, part->fs_type ?
1480 part->fs_type->name : "");
1483 name = ped_partition_get_name (part);
1484 str_list_append (row, name);
1487 flags = partition_print_flags (part);
1488 str_list_append (row, flags);
1492 str_list_append (row, "");
1493 str_list_append (row, _("Free Space"));
1495 str_list_append (row, "");
1496 str_list_append (row, "");
1499 //PED_ASSERT (row.cols == caption.cols)
1500 table_add_row_from_strlist (table, row);
1501 str_list_destroy (row);
1508 table_rendered = table_render (table);
1510 printf("%ls\n", table_rendered);
1512 printf("%s\n", table_rendered);
1514 ped_free (table_rendered);
1515 table_destroy (table);
1516 str_list_destroy (row1);
1520 for (part = ped_disk_next_partition (disk, NULL); part;
1521 part = ped_disk_next_partition (disk, part)) {
1523 if ((!has_free_arg && !ped_partition_is_active(part)) ||
1524 part->type & PED_PARTITION_METADATA)
1528 printf ("%d:", part->num);
1530 fputs ("1:", stdout);
1532 printf ("%s:", ped_unit_format (*dev, part->geom.start));
1533 printf ("%s:", ped_unit_format_byte (
1535 (part->geom.end + 1) *
1536 (*dev)->sector_size - 1));
1538 if (ped_unit_get_default() != PED_UNIT_CHS)
1539 printf ("%s:", ped_unit_format (*dev,
1540 part->geom.length));
1542 if (!(part->type & PED_PARTITION_FREESPACE)) {
1545 printf ("%s:", part->fs_type->name);
1550 printf ("%s:", _(ped_partition_get_name (part)));
1554 printf ("%s;\n", partition_print_flags (part));
1562 ped_disk_destroy (disk);
1566 ped_disk_destroy (disk);
1574 PedDevice *current_dev = NULL;
1576 ped_device_probe_all();
1578 while ((current_dev = ped_device_get_next(current_dev))) {
1579 do_print (¤t_dev);
1587 do_quit (PedDevice** dev)
1593 static PedPartitionType
1594 _disk_get_part_type_for_sector (PedDisk* disk, PedSector sector)
1596 PedPartition* extended;
1598 extended = ped_disk_extended_partition (disk);
1600 || !ped_geometry_test_sector_inside (&extended->geom, sector))
1603 return PED_PARTITION_LOGICAL;
1606 /* This function checks if "part" contains a file system, and returs
1607 * 0 if either no file system was found, or the user declined to add it.
1608 * 1 if a file system was found, and the user chose to add it.
1609 * -1 if the user chose to cancel the entire search.
1612 _rescue_add_partition (PedPartition* part)
1614 const PedFileSystemType* fs_type;
1615 PedGeometry* probed;
1616 PedExceptionOption ex_opt;
1617 PedConstraint* constraint;
1621 fs_type = ped_file_system_probe (&part->geom);
1624 probed = ped_file_system_probe_specific (fs_type, &part->geom);
1628 if (!ped_geometry_test_inside (&part->geom, probed)) {
1629 ped_geometry_destroy (probed);
1633 constraint = ped_constraint_exact (probed);
1634 if (!ped_disk_set_partition_geom (part->disk, part, constraint,
1635 probed->start, probed->end)) {
1636 ped_constraint_destroy (constraint);
1639 ped_constraint_destroy (constraint);
1641 found_start = ped_unit_format (probed->dev, probed->start);
1642 found_end = ped_unit_format (probed->dev, probed->end);
1643 ex_opt = ped_exception_throw (
1644 PED_EXCEPTION_INFORMATION,
1645 PED_EXCEPTION_YES_NO_CANCEL,
1646 _("A %s %s partition was found at %s -> %s. "
1647 "Do you want to add it to the partition table?"),
1648 fs_type->name, ped_partition_type_get_name (part->type),
1649 found_start, found_end);
1650 ped_geometry_destroy (probed);
1651 ped_free (found_start);
1652 ped_free (found_end);
1655 case PED_EXCEPTION_CANCEL: return -1;
1656 case PED_EXCEPTION_NO: return 0;
1660 ped_partition_set_system (part, fs_type);
1661 ped_disk_commit (part->disk);
1665 /* hack: we only iterate through the start, since most (all) fs's have their
1666 * superblocks at the start. We'll need to change this if we generalize
1667 * for RAID, or something...
1670 _rescue_pass (PedDisk* disk, PedGeometry* start_range, PedGeometry* end_range)
1673 PedGeometry start_geom_exact;
1674 PedGeometry entire_dev;
1675 PedConstraint constraint;
1677 PedPartitionType part_type;
1679 part_type = _disk_get_part_type_for_sector (
1680 disk, (start_range->start + end_range->end) / 2);
1682 ped_geometry_init (&entire_dev, disk->dev, 0, disk->dev->length);
1684 ped_timer_reset (g_timer);
1685 ped_timer_set_state_name (g_timer, _("searching for file systems"));
1686 for (start = start_range->start; start <= start_range->end; start++) {
1687 ped_timer_update (g_timer, 1.0 * (start - start_range->start)
1688 / start_range->length);
1690 ped_geometry_init (&start_geom_exact, disk->dev, start, 1);
1691 ped_constraint_init (
1692 &constraint, ped_alignment_any, ped_alignment_any,
1693 &start_geom_exact, &entire_dev,
1694 1, disk->dev->length);
1695 part = ped_partition_new (disk, part_type, NULL, start,
1698 ped_constraint_done (&constraint);
1702 ped_exception_fetch_all ();
1703 if (ped_disk_add_partition (disk, part, &constraint)) {
1704 ped_exception_leave_all ();
1705 switch (_rescue_add_partition (part)) {
1707 ped_constraint_done (&constraint);
1711 ped_disk_remove_partition (disk, part);
1715 goto error_remove_partition;
1718 ped_exception_leave_all ();
1720 ped_partition_destroy (part);
1721 ped_constraint_done (&constraint);
1723 ped_timer_update (g_timer, 1.0);
1727 error_remove_partition:
1728 ped_disk_remove_partition (disk, part);
1729 ped_partition_destroy (part);
1730 ped_constraint_done (&constraint);
1735 do_rescue (PedDevice** dev)
1738 PedSector start = 0, end = 0;
1740 PedGeometry probe_start_region;
1741 PedGeometry probe_end_region;
1743 disk = ped_disk_new (*dev);
1747 if (!command_line_get_sector (_("Start?"), *dev, &start, NULL))
1748 goto error_destroy_disk;
1749 if (!command_line_get_sector (_("End?"), *dev, &end, NULL))
1750 goto error_destroy_disk;
1752 fuzz = PED_MAX (PED_MIN ((end - start) / 10, MEGABYTE_SECTORS(*dev)),
1753 MEGABYTE_SECTORS(*dev) * 16);
1755 ped_geometry_init (&probe_start_region, *dev,
1756 PED_MAX(start - fuzz, 0),
1757 PED_MIN(2 * fuzz, (*dev)->length - (start - fuzz)));
1758 ped_geometry_init (&probe_end_region, *dev,
1759 PED_MAX(end - fuzz, 0),
1760 PED_MIN(2 * fuzz, (*dev)->length - (end - fuzz)));
1762 if (!_rescue_pass (disk, &probe_start_region, &probe_end_region))
1763 goto error_destroy_disk;
1765 ped_disk_destroy (disk);
1767 if ((*dev)->type != PED_DEVICE_FILE)
1768 disk_is_modified = 1;
1773 ped_disk_destroy (disk);
1779 do_resize (PedDevice** dev)
1782 PedPartition *part = NULL;
1784 PedConstraint *constraint;
1785 PedSector start, end;
1786 PedGeometry *range_start = NULL, *range_end = NULL;
1787 PedGeometry new_geom;
1789 disk = ped_disk_new (*dev);
1793 if (!command_line_get_partition (_("Partition number?"), disk, &part))
1794 goto error_destroy_disk;
1795 if (part->type != PED_PARTITION_EXTENDED) {
1796 if (!_partition_warn_busy (part))
1797 goto error_destroy_disk;
1800 start = part->geom.start;
1801 end = part->geom.end;
1802 if (!command_line_get_sector (_("Start?"), *dev, &start, &range_start))
1803 goto error_destroy_disk;
1804 if (!command_line_get_sector (_("End?"), *dev, &end, &range_end))
1805 goto error_destroy_disk;
1807 if (!ped_geometry_init (&new_geom, *dev, start, end - start + 1))
1808 goto error_destroy_disk;
1809 snap_to_boundaries (&new_geom, &part->geom, disk,
1810 range_start, range_end);
1812 if (part->type == PED_PARTITION_EXTENDED) {
1813 constraint = constraint_from_start_end (*dev,
1814 range_start, range_end);
1815 if (!ped_disk_set_partition_geom (disk, part, constraint,
1816 new_geom.start, new_geom.end))
1817 goto error_destroy_constraint;
1818 ped_partition_set_system (part, NULL);
1820 fs = ped_file_system_open (&part->geom);
1822 goto error_destroy_disk;
1823 constraint = constraint_intersect_and_destroy (
1824 ped_file_system_get_resize_constraint (fs),
1825 constraint_from_start_end (
1826 *dev, range_start, range_end));
1827 if (!ped_disk_set_partition_geom (disk, part, constraint,
1828 new_geom.start, new_geom.end))
1829 goto error_close_fs;
1830 if (!ped_file_system_resize (fs, &part->geom, g_timer))
1831 goto error_close_fs;
1832 /* may have changed... eg fat16 -> fat32 */
1833 ped_partition_set_system (part, fs->type);
1834 ped_file_system_close (fs);
1837 ped_disk_commit (disk);
1838 ped_constraint_destroy (constraint);
1839 ped_disk_destroy (disk);
1840 if (range_start != NULL)
1841 ped_geometry_destroy (range_start);
1842 if (range_end != NULL)
1843 ped_geometry_destroy (range_end);
1845 if ((*dev)->type != PED_DEVICE_FILE)
1846 disk_is_modified = 1;
1851 ped_file_system_close (fs);
1852 error_destroy_constraint:
1853 ped_constraint_destroy (constraint);
1855 ped_disk_destroy (disk);
1857 if (range_start != NULL)
1858 ped_geometry_destroy (range_start);
1859 if (range_end != NULL)
1860 ped_geometry_destroy (range_end);
1865 do_rm (PedDevice** dev)
1868 PedPartition* part = NULL;
1870 disk = ped_disk_new (*dev);
1874 if (!command_line_get_partition (_("Partition number?"), disk, &part))
1875 goto error_destroy_disk;
1876 if (!_partition_warn_busy (part))
1877 goto error_destroy_disk;
1879 ped_disk_delete_partition (disk, part);
1880 ped_disk_commit (disk);
1881 ped_disk_destroy (disk);
1883 if ((*dev)->type != PED_DEVICE_FILE)
1884 disk_is_modified = 1;
1889 ped_disk_destroy (disk);
1895 do_select (PedDevice** dev)
1897 PedDevice* new_dev = *dev;
1899 if (!command_line_get_device (_("New device?"), &new_dev))
1901 if (!ped_device_open (new_dev))
1904 ped_device_close (*dev);
1906 print_using_dev (*dev);
1911 do_set (PedDevice** dev)
1914 PedPartition* part = NULL;
1915 PedPartitionFlag flag;
1918 disk = ped_disk_new (*dev);
1922 if (!command_line_get_partition (_("Partition number?"), disk, &part))
1923 goto error_destroy_disk;
1924 if (!command_line_get_part_flag (_("Flag to Invert?"), part, &flag))
1925 goto error_destroy_disk;
1926 state = (ped_partition_get_flag (part, flag) == 0 ? 1 : 0);
1928 if (!is_toggle_mode) {
1929 if (!command_line_get_state (_("New state?"), &state))
1930 goto error_destroy_disk;
1933 if (!ped_partition_set_flag (part, flag, state))
1934 goto error_destroy_disk;
1935 if (!ped_disk_commit (disk))
1936 goto error_destroy_disk;
1937 ped_disk_destroy (disk);
1939 if ((*dev)->type != PED_DEVICE_FILE)
1940 disk_is_modified = 1;
1945 ped_disk_destroy (disk);
1951 do_toggle (PedDevice **dev)
1956 result = do_set (dev);
1963 do_unit (PedDevice** dev)
1965 PedUnit unit = ped_unit_get_default ();
1966 if (!command_line_get_unit (_("Unit?"), &unit))
1968 ped_unit_set_default (unit);
1986 PedFileSystemType* fs_type;
1987 PedDiskType* disk_type;
1988 PedPartitionFlag part_flag;
1993 list = str_list_create (_(flag_msg_start), NULL);
1994 for (part_flag = ped_partition_flag_next (0); part_flag;
1995 part_flag = ped_partition_flag_next (part_flag)) {
1999 str_list_append (list, ", ");
2000 str_list_append (list,
2001 _(ped_partition_flag_get_name (part_flag)));
2003 str_list_append (list, "\n");
2005 flag_msg = str_list_convert (list);
2006 str_list_destroy (list);
2010 list = str_list_create (_(unit_msg_start), NULL);
2011 for (unit = PED_UNIT_FIRST; unit <= PED_UNIT_LAST; unit++) {
2015 str_list_append (list, ", ");
2016 str_list_append (list, ped_unit_get_name (unit));
2018 str_list_append (list, "\n");
2020 unit_msg = str_list_convert (list);
2021 str_list_destroy (list);
2024 list = str_list_create (_(label_type_msg_start), NULL);
2027 for (disk_type = ped_disk_type_get_next (NULL);
2028 disk_type; disk_type = ped_disk_type_get_next (disk_type)) {
2029 if (disk_type->ops->write == NULL)
2035 str_list_append (list, ", ");
2036 str_list_append (list, disk_type->name);
2038 str_list_append (list, "\n");
2040 label_type_msg = str_list_convert (list);
2041 str_list_destroy (list);
2043 /* mkfs - file system types */
2044 list = str_list_create (_(fs_type_msg_start), NULL);
2047 for (fs_type = ped_file_system_type_get_next (NULL);
2048 fs_type; fs_type = ped_file_system_type_get_next (fs_type)) {
2049 if (fs_type->ops->create == NULL)
2055 str_list_append (list, ", ");
2056 str_list_append (list, fs_type->name);
2058 str_list_append (list, "\n");
2060 mkfs_fs_type_msg = str_list_convert (list);
2061 str_list_destroy (list);
2063 /* mkpart - file system types */
2064 list = str_list_create (_(fs_type_msg_start), NULL);
2067 for (fs_type = ped_file_system_type_get_next (NULL);
2068 fs_type; fs_type = ped_file_system_type_get_next (fs_type)) {
2072 str_list_append (list, ", ");
2073 str_list_append (list, fs_type->name);
2075 str_list_append (list, "\n");
2077 mkpart_fs_type_msg = str_list_convert (list);
2078 str_list_destroy (list);
2080 /* resize - file system types */
2081 list = str_list_create (_(resize_msg_start), NULL);
2084 for (fs_type = ped_file_system_type_get_next (NULL);
2085 fs_type; fs_type = ped_file_system_type_get_next (fs_type)) {
2086 if (fs_type->ops->resize == NULL)
2092 str_list_append (list, ", ");
2093 str_list_append (list, fs_type->name);
2095 str_list_append (list, "\n");
2097 resize_fs_type_msg = str_list_convert (list);
2098 str_list_destroy (list);
2105 free (mkfs_fs_type_msg);
2106 free (mkpart_fs_type_msg);
2107 free (resize_fs_type_msg);
2108 free (label_type_msg);
2114 command_register (commands, command_create (
2115 str_list_create_unique ("check", _("check"), NULL),
2118 _("check NUMBER do a simple check on the file "
2121 str_list_create (_(number_msg), NULL), 1));
2123 command_register (commands, command_create (
2124 str_list_create_unique ("cp", _("cp"), NULL),
2127 _("cp [FROM-DEVICE] FROM-NUMBER TO-NUMBER copy file system to another "
2130 str_list_create (_(number_msg), _(device_msg), NULL), 1));
2132 command_register (commands, command_create (
2133 str_list_create_unique ("help", _("help"), NULL),
2136 _("help [COMMAND] print general help, or help "
2141 command_register (commands, command_create (
2142 str_list_create_unique ("mklabel", _("mklabel"), "mktable", _("mktable"), NULL),
2145 _("mklabel,mktable LABEL-TYPE create a new disklabel "
2146 "(partition table)"),
2148 str_list_create (label_type_msg, NULL), 1));
2150 command_register (commands, command_create (
2151 str_list_create_unique ("mkfs", _("mkfs"), NULL),
2154 _("mkfs NUMBER FS-TYPE make a FS-TYPE file "
2155 "system on partititon NUMBER"),
2157 str_list_create (_(number_msg), _(mkfs_fs_type_msg), NULL), 1));
2159 command_register (commands, command_create (
2160 str_list_create_unique ("mkpart", _("mkpart"), NULL),
2163 _("mkpart PART-TYPE [FS-TYPE] START END make a partition"),
2165 str_list_create (_(part_type_msg),
2166 _(mkpart_fs_type_msg),
2169 _("'mkpart' makes a partition without creating a new file system on the "
2170 "partition. FS-TYPE may be specified to set an appropriate partition ID.\n"),
2173 command_register (commands, command_create (
2174 str_list_create_unique ("mkpartfs", _("mkpartfs"), NULL),
2177 _("mkpartfs PART-TYPE FS-TYPE START END make a partition with a "
2180 str_list_create (_(part_type_msg), _(start_end_msg), NULL), 1));
2182 command_register (commands, command_create (
2183 str_list_create_unique ("move", _("move"), NULL),
2186 _("move NUMBER START END move partition NUMBER"),
2188 str_list_create (_(number_msg), _(start_end_msg), NULL), 1));
2190 command_register (commands, command_create (
2191 str_list_create_unique ("name", _("name"), NULL),
2194 _("name NUMBER NAME name partition NUMBER as NAME"),
2196 str_list_create (_(number_msg), _(name_msg), NULL), 1));
2198 command_register (commands, command_create (
2199 str_list_create_unique ("print", _("print"), NULL),
2202 _("print [devices|free|list,all|NUMBER] display the partition table, "
2203 "available devices, free space, all found partitions, or a particular "
2207 _("Without arguments, 'print' displays the entire partition table. However "
2208 "with the following arguments it performs various other actions.\n"),
2209 _(" devices : display all active block devices\n"),
2210 _(" free : display information about free unpartitioned space on the "
2211 "current block device\n"),
2212 _(" list, all : display the partition tables of all active block devices\n"),
2213 _(" NUMBER : display more detailed information about this particular "
2217 command_register (commands, command_create (
2218 str_list_create_unique ("quit", _("quit"), NULL),
2221 _("quit exit program"),
2225 command_register (commands, command_create (
2226 str_list_create_unique ("rescue", _("rescue"), NULL),
2229 _("rescue START END rescue a lost partition near "
2232 str_list_create (_(start_end_msg), NULL), 1));
2234 command_register (commands, command_create (
2235 str_list_create_unique ("resize", _("resize"), NULL),
2238 _("resize NUMBER START END resize partition NUMBER and "
2241 str_list_create (_(number_msg),
2243 _(resize_fs_type_msg), NULL), 1));
2245 command_register (commands, command_create (
2246 str_list_create_unique ("rm", _("rm"), NULL),
2249 _("rm NUMBER delete partition NUMBER"),
2251 str_list_create (_(number_msg), NULL), 1));
2253 command_register (commands, command_create (
2254 str_list_create_unique ("select", _("select"), NULL),
2257 _("select DEVICE choose the device to edit"),
2259 str_list_create (_(device_msg), NULL), 1));
2261 command_register (commands, command_create (
2262 str_list_create_unique ("set", _("set"), NULL),
2265 _("set NUMBER FLAG STATE change the FLAG on partition "
2268 str_list_create (_(number_msg), flag_msg, _(state_msg), NULL), 1));
2270 command_register (commands, command_create (
2271 str_list_create_unique ("toggle", _("toggle"), NULL),
2274 _("toggle [NUMBER [FLAG]] toggle the state of FLAG on "
2275 "partition NUMBER"),
2277 str_list_create (_(number_msg), flag_msg, NULL), 1));
2279 command_register (commands, command_create (
2280 str_list_create_unique ("unit", _("unit"), NULL),
2283 _("unit UNIT set the default unit to UNIT"),
2285 str_list_create (unit_msg, NULL), 1));
2287 command_register (commands, command_create (
2288 str_list_create_unique ("version", _("version"), NULL),
2291 _("version display the version number "
2292 "and copyright information of GNU Parted"),
2295 _("'version' displays copyright and version information corresponding to this "
2296 "copy of GNU Parted\n"),
2306 for (walk = commands; *walk; walk++) {
2307 command_destroy (*walk);
2315 /* intialize i18n */
2317 setlocale(LC_ALL, "");
2318 bindtextdomain(PACKAGE, LOCALEDIR);
2319 textdomain(PACKAGE);
2320 #endif /* ENABLE_NLS */
2326 version_etc (stdout, PROGRAM_NAME, PACKAGE_NAME, VERSION, AUTHORS,
2331 _parse_options (int* argc_ptr, char*** argv_ptr)
2333 int opt, help = 0, list = 0, version = 0, wrong = 0;
2337 opt = getopt_long (*argc_ptr, *argv_ptr, "hilmsv",
2343 case 'h': help = 1; break;
2344 case 'l': list = 1; break;
2345 case 'm': opt_machine_mode = 1; break;
2346 case 's': opt_script_mode = 1; break;
2347 case 'v': version = 1; break;
2348 case PRETEND_INPUT_TTY:
2349 pretend_input_tty = 1;
2351 default: wrong = 1; break;
2357 _("Usage: %s [-hlmsv] [DEVICE [COMMAND [PARAMETERS]]...]\n"),
2364 exit (EXIT_SUCCESS);
2369 exit (EXIT_SUCCESS);
2374 exit (EXIT_SUCCESS);
2377 *argc_ptr -= optind;
2378 *argv_ptr += optind;
2383 _choose_device (int* argc_ptr, char*** argv_ptr)
2387 /* specified on comand line? */
2389 dev = ped_device_get ((*argv_ptr) [0]);
2396 ped_device_probe_all ();
2397 dev = ped_device_get_next (NULL);
2399 if (ped_exception_throw (PED_EXCEPTION_ERROR,
2400 PED_EXCEPTION_RETRY_CANCEL,
2401 _("No device found"))
2402 == PED_EXCEPTION_RETRY)
2409 if (!ped_device_open (dev))
2415 _init (int* argc_ptr, char*** argv_ptr)
2419 #ifdef ENABLE_MTRACE
2429 if (!_parse_options (argc_ptr, argv_ptr))
2430 goto error_done_commands;
2433 if (getuid() != 0 && !opt_script_mode) {
2434 puts (_("WARNING: You are not superuser. Watch out for "
2439 dev = _choose_device (argc_ptr, argv_ptr);
2441 goto error_done_commands;
2443 g_timer = ped_timer_new (_timer_handler, &timer_context);
2445 goto error_done_commands;
2446 timer_context.last_update = 0;
2450 error_done_commands:
2459 _done (PedDevice* dev)
2461 if (dev->boot_dirty && dev->type != PED_DEVICE_FILE) {
2462 ped_exception_throw (
2463 PED_EXCEPTION_WARNING,
2465 _("You should reinstall your boot loader before "
2466 "rebooting. Read section 4 of the Parted User "
2467 "documentation for more information."));
2469 if (!opt_script_mode && !opt_machine_mode && disk_is_modified) {
2470 ped_exception_throw (
2471 PED_EXCEPTION_INFORMATION, PED_EXCEPTION_OK,
2472 _("You may need to update /etc/fstab.\n"));
2475 ped_device_close (dev);
2477 ped_timer_destroy (g_timer);
2484 main (int argc, char** argv)
2489 program_name = argv[0];
2490 atexit (close_stdout);
2492 dev = _init (&argc, &argv);
2496 if (argc || opt_script_mode)
2497 status = non_interactive_mode (&dev, commands, argc, argv);
2499 status = interactive_mode (&dev, commands);