parted.c revision 9663:ace9a2ac3683
1/* 2 parted - a frontend to libparted 3 Copyright (C) 1999, 2000, 2001, 2002, 2003, 2005, 2006, 2007 4 Free Software Foundation, Inc. 5 6 This program is free software; you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation; either version 3 of the License, or 9 (at your option) any later version. 10 11 This program is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 GNU General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with this program. If not, see <http://www.gnu.org/licenses/>. 18*/ 19 20#include <config.h> 21 22#include "closeout.h" 23#include "configmake.h" 24#include "version-etc.h" 25#include "command.h" 26#include "ui.h" 27#include "table.h" 28 29#define AUTHORS \ 30 "<http://parted.alioth.debian.org/cgi-bin/trac.cgi/browser/AUTHORS>" 31 32/* The official name of this program (e.g., no `g' prefix). */ 33#define PROGRAM_NAME "parted" 34 35#define N_(String) String 36#if ENABLE_NLS 37# include <libintl.h> 38# include <locale.h> 39# define _(String) dgettext (PACKAGE, String) 40#else 41# define _(String) (String) 42#endif /* ENABLE_NLS */ 43 44#include <parted/parted.h> 45#include <parted/debug.h> 46 47#include <ctype.h> 48#include <stdarg.h> 49#include <stdlib.h> 50#include <string.h> 51#include <unistd.h> 52#include <limits.h> 53#include "xalloc.h" 54 55#ifdef ENABLE_MTRACE 56#include <mcheck.h> 57#endif 58 59#include <getopt.h> 60 61/* minimum amount of free space to leave, or maximum amount to gobble up */ 62#define MIN_FREESPACE (1000 * 2) /* 1000k */ 63 64static int MEGABYTE_SECTORS (PedDevice* dev) 65{ 66 return PED_MEGABYTE_SIZE / dev->sector_size; 67} 68 69/* For long options that have no equivalent short option, use a 70 non-character as a pseudo short option, starting with CHAR_MAX + 1. */ 71enum 72{ 73 PRETEND_INPUT_TTY = CHAR_MAX + 1, 74}; 75 76 77typedef struct { 78 time_t last_update; 79 time_t predicted_time_left; 80} TimerContext; 81 82static struct option options[] = { 83 /* name, has-arg, string-return-val, char-return-val */ 84 {"help", 0, NULL, 'h'}, 85 {"list", 0, NULL, 'l'}, 86 {"machine", 0, NULL, 'm'}, 87 {"script", 0, NULL, 's'}, 88 {"version", 0, NULL, 'v'}, 89 {"-pretend-input-tty", 0, NULL, PRETEND_INPUT_TTY}, 90 {NULL, 0, NULL, 0} 91}; 92 93static char* options_help [][2] = { 94 {"help", N_("displays this help message")}, 95 {"list", N_("lists partition layout on all block devices")}, 96 {"machine", N_("displays machine parseable output")}, 97 {"script", N_("never prompts for user intervention")}, 98 {"version", N_("displays the version")}, 99 {NULL, NULL} 100}; 101 102char *program_name; 103 104int opt_script_mode = 0; 105int pretend_input_tty = 0; 106int opt_machine_mode = 0; 107int disk_is_modified = 0; 108int is_toggle_mode = 0; 109 110static char* number_msg = N_( 111"NUMBER is the partition number used by Linux. On MS-DOS disk labels, the " 112"primary partitions number from 1 to 4, logical partitions from 5 onwards.\n"); 113 114static char* label_type_msg_start = N_("LABEL-TYPE is one of: "); 115static char* flag_msg_start = N_("FLAG is one of: "); 116static char* unit_msg_start = N_("UNIT is one of: "); 117static char* part_type_msg = N_("PART-TYPE is one of: primary, logical, " 118 "extended\n"); 119static char* fs_type_msg_start = N_("FS-TYPE is one of: "); 120static char* start_end_msg = N_("START and END are disk locations, such as " 121 "4GB or 10%. Negative values count from the end of the disk. " 122 "For example, -1s specifies exactly the last sector.\n"); 123static char* state_msg = N_("STATE is one of: on, off\n"); 124static char* device_msg = N_("DEVICE is usually /dev/hda or /dev/sda\n"); 125static char* name_msg = N_("NAME is any word you want\n"); 126static char* resize_msg_start = N_("The partition must have one of the " 127 "following FS-TYPEs: "); 128 129static char* copyright_msg = N_( 130"Copyright (C) 1998 - 2006 Free Software Foundation, Inc.\n" 131"This program is free software, covered by the GNU General Public License.\n" 132"\n" 133"This program is distributed in the hope that it will be useful,\n" 134"but WITHOUT ANY WARRANTY; without even the implied warranty of\n" 135"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" 136"GNU General Public License for more details.\n\n"); 137 138static char* label_type_msg; 139static char* flag_msg; 140static char* unit_msg; 141 142static char* mkfs_fs_type_msg; 143static char* mkpart_fs_type_msg; 144static char* resize_fs_type_msg; 145 146static Command* commands [256] = {NULL}; 147static PedTimer* g_timer; 148static TimerContext timer_context; 149 150static int _print_list (); 151static void _done (PedDevice* dev); 152 153static void 154_timer_handler (PedTimer* timer, void* context) 155{ 156 TimerContext* tcontext = (TimerContext*) context; 157 int draw_this_time; 158 159 if (opt_script_mode || !isatty(fileno(stdout))) 160 return; 161 162 if (tcontext->last_update != timer->now && timer->now > timer->start) { 163 tcontext->predicted_time_left 164 = timer->predicted_end - timer->now; 165 tcontext->last_update = timer->now; 166 draw_this_time = 1; 167 } else { 168 draw_this_time = 0; 169 } 170 171 if (draw_this_time) { 172 wipe_line (); 173 174 if (timer->state_name) 175 printf ("%s... ", timer->state_name); 176 printf (_("%0.f%%\t(time left %.2d:%.2d)"), 177 100.0 * timer->frac, 178 (int) (tcontext->predicted_time_left / 60), 179 (int) (tcontext->predicted_time_left % 60)); 180 181 fflush (stdout); 182 } 183} 184 185static int 186_partition_warn_busy (PedPartition* part) 187{ 188 char* path; 189 190 if (ped_partition_is_busy (part)) { 191 path = ped_partition_get_path (part); 192 ped_exception_throw ( 193 PED_EXCEPTION_ERROR, 194 PED_EXCEPTION_CANCEL, 195 _("Partition %s is being used. You must unmount it " 196 "before you modify it with Parted."), 197 path); 198 ped_free (path); 199 return 0; 200 } 201 return 1; 202} 203 204static int 205_disk_warn_busy (PedDisk* disk) 206{ 207 if (ped_device_is_busy (disk->dev)) 208 return ped_exception_throw ( 209 (opt_script_mode 210 ? PED_EXCEPTION_ERROR 211 : PED_EXCEPTION_WARNING), 212 PED_EXCEPTION_IGNORE_CANCEL, 213 _("Partition(s) on %s are being used."), 214 disk->dev->path) == PED_EXCEPTION_IGNORE; 215 216 return 1; 217} 218 219static int 220_partition_warn_loss () 221{ 222 return ped_exception_throw ( 223 PED_EXCEPTION_WARNING, 224 PED_EXCEPTION_YES_NO, 225 _("The existing file system will be destroyed and " 226 "all data on the partition will be lost. Do " 227 "you want to continue?"), 228 NULL) == PED_EXCEPTION_YES; 229} 230 231static int 232_disk_warn_loss (PedDisk* disk) 233{ 234 return ped_exception_throw ( 235 PED_EXCEPTION_WARNING, 236 PED_EXCEPTION_YES_NO, 237 _("The existing disk label on %s will be destroyed " 238 "and all data on this disk will be lost. Do you " 239 "want to continue?"), 240 disk->dev->path) == PED_EXCEPTION_YES; 241} 242 243/* This function changes "sector" to "new_sector" if the new value lies 244 * within the required range. 245 */ 246static int 247snap (PedSector* sector, PedSector new_sector, PedGeometry* range) 248{ 249 PED_ASSERT (ped_geometry_test_sector_inside (range, *sector), return 0); 250 if (!ped_geometry_test_sector_inside (range, new_sector)) 251 return 0; 252 *sector = new_sector; 253 return 1; 254} 255 256typedef enum { 257 MOVE_NO = 0, 258 MOVE_STILL = 1, 259 MOVE_UP = 2, 260 MOVE_DOWN = 4 261} EMoves; 262 263enum { /* Don't change these values */ 264 SECT_START = 0, 265 SECT_END = -1 266}; 267 268/* Find the prefered way to adjust the sector s inside range. 269 * If a move isn't allowed or is out of range it can't be selected. 270 * what contains SECT_START if the sector to adjust is a start sector 271 * or SECT_END if it's an end one. 272 * The prefered move is to the nearest allowed boundary of the part 273 * partition (if at equal distance: to start if SECT_START or to end 274 * if SECT_END). 275 * The distance is returned in dist. 276 */ 277static EMoves 278prefer_snap (PedSector s, int what, PedGeometry* range, EMoves* allow, 279 PedPartition* part, PedSector* dist) 280{ 281 PedSector up_dist = -1, down_dist = -1; 282 PedSector new_sect; 283 EMoves move; 284 285 PED_ASSERT (what == SECT_START || what == SECT_END, return 0); 286 287 if (!(*allow & (MOVE_UP | MOVE_DOWN))) { 288 *dist = 0; 289 return MOVE_STILL; 290 } 291 292 if (*allow & MOVE_UP) { 293 new_sect = part->geom.end + 1 + what; 294 if (ped_geometry_test_sector_inside (range, new_sect)) 295 up_dist = new_sect - s; 296 else 297 *allow &= ~MOVE_UP; 298 } 299 300 if (*allow & MOVE_DOWN) { 301 new_sect = part->geom.start + what; 302 if (ped_geometry_test_sector_inside (range, new_sect)) 303 down_dist = s - new_sect; 304 else 305 *allow &= ~MOVE_DOWN; 306 } 307 308 move = MOVE_STILL; 309 if ((*allow & MOVE_UP) && (*allow & MOVE_DOWN)) { 310 if (down_dist < up_dist || (down_dist == up_dist 311 && what == SECT_START) ) 312 move = MOVE_DOWN; 313 else if (up_dist < down_dist || (down_dist == up_dist 314 && what == SECT_END) ) 315 move = MOVE_UP; 316 else 317 PED_ASSERT (0, return 0); 318 } else if (*allow & MOVE_UP) 319 move = MOVE_UP; 320 else if (*allow & MOVE_DOWN) 321 move = MOVE_DOWN; 322 323 *dist = ( move == MOVE_DOWN ? down_dist : 324 ( move == MOVE_UP ? up_dist : 325 0 ) ); 326 return move; 327} 328 329/* Snaps a partition to nearby partition boundaries. This is useful for 330 * gobbling up small amounts of free space, and also for reinterpreting small 331 * changes to a partition as non-changes (eg: perhaps the user only wanted to 332 * resize the end of a partition). 333 * Note that this isn't the end of the story... this function is 334 * always called before the constraint solver kicks in. So you don't need to 335 * worry too much about inadvertantly creating overlapping partitions, etc. 336 */ 337static void 338snap_to_boundaries (PedGeometry* new_geom, PedGeometry* old_geom, 339 PedDisk* disk, 340 PedGeometry* start_range, PedGeometry* end_range) 341{ 342 PedPartition* start_part; 343 PedPartition* end_part; 344 PedSector start = new_geom->start; 345 PedSector end = new_geom->end; 346 PedSector start_dist = -1, end_dist = -1; 347 EMoves start_allow, end_allow, start_want, end_want; 348 int adjacent; 349 350 start_want = end_want = MOVE_NO; 351 start_allow = end_allow = MOVE_STILL | MOVE_UP | MOVE_DOWN; 352 353 start_part = ped_disk_get_partition_by_sector (disk, start); 354 end_part = ped_disk_get_partition_by_sector (disk, end); 355 adjacent = (start_part->geom.end + 1 == end_part->geom.start); 356 357 /* If we can snap to old_geom, then we will... */ 358 /* and this will enforce the snapped positions */ 359 if (old_geom) { 360 if (snap (&start, old_geom->start, start_range)) 361 start_allow = MOVE_STILL; 362 if (snap (&end, old_geom->end, end_range)) 363 end_allow = MOVE_STILL; 364 } 365 366 /* If start and end are on the same partition, we */ 367 /* don't allow them to cross. */ 368 if (start_part == end_part) { 369 start_allow &= ~MOVE_UP; 370 end_allow &= ~MOVE_DOWN; 371 } 372 373 /* Let's find our way */ 374 start_want = prefer_snap (start, SECT_START, start_range, &start_allow, 375 start_part, &start_dist ); 376 end_want = prefer_snap (end, SECT_END, end_range, &end_allow, 377 end_part, &end_dist ); 378 379 PED_ASSERT (start_dist >= 0 && end_dist >= 0, return); 380 381 /* If start and end are on adjacent partitions, */ 382 /* and if they would prefer crossing, then refrain */ 383 /* the farthest to do so. */ 384 if (adjacent && start_want == MOVE_UP && end_want == MOVE_DOWN) { 385 if (end_dist < start_dist) { 386 start_allow &= ~MOVE_UP; 387 start_want = prefer_snap (start, SECT_START, 388 start_range, &start_allow, 389 start_part, &start_dist ); 390 PED_ASSERT (start_dist >= 0, return); 391 } else { 392 end_allow &= ~MOVE_DOWN; 393 end_want = prefer_snap (end, SECT_END, 394 end_range, &end_allow, 395 end_part, &end_dist ); 396 PED_ASSERT (end_dist >= 0, return); 397 } 398 } 399 400 /* New positions */ 401 start = ( start_want == MOVE_DOWN ? start_part->geom.start : 402 ( start_want == MOVE_UP ? start_part->geom.end + 1 : 403 start ) ); 404 end = ( end_want == MOVE_DOWN ? end_part->geom.start - 1 : 405 ( end_want == MOVE_UP ? end_part->geom.end : 406 end ) ); 407 PED_ASSERT (ped_geometry_test_sector_inside(start_range,start), return); 408 PED_ASSERT (ped_geometry_test_sector_inside (end_range, end), return); 409 PED_ASSERT (start <= end, 410 PED_DEBUG (0, "start = %d, end = %d\n", start, end)); 411 ped_geometry_set (new_geom, start, end - start + 1); 412} 413 414/* This functions constructs a constraint from the following information: 415 * start, is_start_exact, end, is_end_exact. 416 * 417 * If is_start_exact == 1, then the constraint requires start be as given in 418 * "start". Otherwise, the constraint does not set any requirements on the 419 * start. 420 */ 421static PedConstraint* 422constraint_from_start_end (PedDevice* dev, PedGeometry* range_start, 423 PedGeometry* range_end) 424{ 425 return ped_constraint_new (ped_alignment_any, ped_alignment_any, 426 range_start, range_end, 1, dev->length); 427} 428 429static PedConstraint* 430constraint_intersect_and_destroy (PedConstraint* a, PedConstraint* b) 431{ 432 PedConstraint* result = ped_constraint_intersect (a, b); 433 ped_constraint_destroy (a); 434 ped_constraint_destroy (b); 435 return result; 436} 437 438void 439help_on (char* topic) 440{ 441 Command* cmd; 442 443 cmd = command_get (commands, topic); 444 if (!cmd) return; 445 446 command_print_help (cmd); 447} 448 449static int 450do_check (PedDevice** dev) 451{ 452 PedDisk* disk; 453 PedFileSystem* fs; 454 PedPartition* part = NULL; 455 456 disk = ped_disk_new (*dev); 457 if (!disk) 458 goto error; 459 460 if (!command_line_get_partition (_("Partition number?"), disk, &part)) 461 goto error_destroy_disk; 462 if (!_partition_warn_busy (part)) 463 goto error_destroy_disk; 464 465 if (!ped_disk_check (disk)) 466 goto error_destroy_disk; 467 468 fs = ped_file_system_open (&part->geom); 469 if (!fs) 470 goto error_destroy_disk; 471 if (!ped_file_system_check (fs, g_timer)) 472 goto error_close_fs; 473 ped_file_system_close (fs); 474 ped_disk_destroy (disk); 475 return 1; 476 477error_close_fs: 478 ped_file_system_close (fs); 479error_destroy_disk: 480 ped_disk_destroy (disk); 481error: 482 return 0; 483} 484 485static int 486do_cp (PedDevice** dev) 487{ 488 PedDisk* src_disk; 489 PedDisk* dst_disk; 490 PedPartition* src = NULL; 491 PedPartition* dst = NULL; 492 PedFileSystem* src_fs; 493 PedFileSystem* dst_fs; 494 PedFileSystemType* dst_fs_type; 495 496 dst_disk = ped_disk_new (*dev); 497 if (!dst_disk) 498 goto error; 499 500 src_disk = dst_disk; 501 if (!command_line_is_integer ()) { 502 if (!command_line_get_disk (_("Source device?"), &src_disk)) 503 goto error_destroy_disk; 504 } 505 506 if (!command_line_get_partition (_("Source partition number?"), 507 src_disk, &src)) 508 goto error_destroy_disk; 509 if (src->type == PED_PARTITION_EXTENDED) { 510 ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, 511 _("Can't copy an extended partition.")); 512 goto error_destroy_disk; 513 } 514 if (!_partition_warn_busy (src)) 515 goto error_destroy_disk; 516 517 if (!command_line_get_partition (_("Destination partition number?"), 518 dst_disk, &dst)) 519 goto error_destroy_disk; 520 if (!_partition_warn_busy (dst)) 521 goto error_destroy_disk; 522 523/* do the copy */ 524 src_fs = ped_file_system_open (&src->geom); 525 if (!src_fs) 526 goto error_destroy_disk; 527 dst_fs = ped_file_system_copy (src_fs, &dst->geom, g_timer); 528 if (!dst_fs) 529 goto error_close_src_fs; 530 dst_fs_type = dst_fs->type; /* may be different to src_fs->type */ 531 ped_file_system_close (src_fs); 532 ped_file_system_close (dst_fs); 533 534/* update the partition table, close disks */ 535 if (!ped_partition_set_system (dst, dst_fs_type)) 536 goto error_destroy_disk; 537 if (!ped_disk_commit (dst_disk)) 538 goto error_destroy_disk; 539 if (src_disk != dst_disk) 540 ped_disk_destroy (src_disk); 541 ped_disk_destroy (dst_disk); 542 543 if ((*dev)->type != PED_DEVICE_FILE) 544 disk_is_modified = 1; 545 546 return 1; 547 548error_close_src_fs: 549 ped_file_system_close (src_fs); 550error_destroy_disk: 551 if (src_disk && src_disk != dst_disk) 552 ped_disk_destroy (src_disk); 553 ped_disk_destroy (dst_disk); 554error: 555 return 0; 556} 557 558void 559print_commands_help () 560{ 561 int i; 562 563 for (i=0; commands [i]; i++) 564 command_print_summary (commands [i]); 565} 566 567void 568print_options_help () 569{ 570 int i; 571 572 for (i=0; options_help [i][0]; i++) { 573 printf (" -%c, --%-23.23s %s\n", 574 options_help [i][0][0], 575 options_help [i][0], 576 _(options_help [i][1])); 577 } 578} 579 580int 581do_help (PedDevice** dev) 582{ 583 if (command_line_get_word_count ()) { 584 char* word = command_line_pop_word (); 585 if (word) { 586 help_on (word); 587 free (word); 588 } 589 } else { 590 print_commands_help(); 591 } 592 return 1; 593} 594 595static int 596do_mklabel (PedDevice** dev) 597{ 598 PedDisk* disk; 599 const PedDiskType* type = ped_disk_probe (*dev); 600 601 ped_exception_fetch_all (); 602 disk = ped_disk_new (*dev); 603 if (!disk) ped_exception_catch (); 604 ped_exception_leave_all (); 605 606 if (disk) { 607 if (!_disk_warn_busy (disk)) 608 goto error_destroy_disk; 609 if (!opt_script_mode && !_disk_warn_loss (disk)) 610 goto error_destroy_disk; 611 612 ped_disk_destroy (disk); 613 } 614 615 if (!command_line_get_disk_type (_("New disk label type?"), &type)) 616 goto error; 617 618 disk = ped_disk_new_fresh (*dev, type); 619 if (!disk) 620 goto error; 621 622 if (!ped_disk_commit (disk)) 623 goto error_destroy_disk; 624 ped_disk_destroy (disk); 625 626 if ((*dev)->type != PED_DEVICE_FILE) 627 disk_is_modified = 1; 628 629 return 1; 630 631error_destroy_disk: 632 ped_disk_destroy (disk); 633error: 634 return 0; 635} 636 637static int 638do_mkfs (PedDevice** dev) 639{ 640 PedDisk* disk; 641 PedPartition* part = NULL; 642 const PedFileSystemType* type = ped_file_system_type_get ("ext2"); 643 PedFileSystem* fs; 644 645 disk = ped_disk_new (*dev); 646 if (!disk) 647 goto error; 648 649 if (!opt_script_mode && !_partition_warn_loss()) 650 goto error_destroy_disk; 651 652 if (!command_line_get_partition (_("Partition number?"), disk, &part)) 653 goto error_destroy_disk; 654 if (!_partition_warn_busy (part)) 655 goto error_destroy_disk; 656 if (!command_line_get_fs_type (_("File system type?"), &type)) 657 goto error_destroy_disk; 658 659 fs = ped_file_system_create (&part->geom, type, g_timer); 660 if (!fs) 661 goto error_destroy_disk; 662 ped_file_system_close (fs); 663 664 if (!ped_partition_set_system (part, type)) 665 goto error_destroy_disk; 666 if (ped_partition_is_flag_available (part, PED_PARTITION_LBA)) 667 ped_partition_set_flag (part, PED_PARTITION_LBA, 1); 668 if (!ped_disk_commit (disk)) 669 goto error_destroy_disk; 670 ped_disk_destroy (disk); 671 672 if ((*dev)->type != PED_DEVICE_FILE) 673 disk_is_modified = 1; 674 675 return 1; 676 677error_destroy_disk: 678 ped_disk_destroy (disk); 679error: 680 return 0; 681} 682 683static int 684do_mkpart (PedDevice** dev) 685{ 686 PedDisk* disk; 687 PedPartition* part; 688 PedPartitionType part_type; 689 const PedFileSystemType* fs_type = ped_file_system_type_get ("ext2"); 690 PedSector start = 0, end = 0; 691 PedGeometry *range_start = NULL, *range_end = NULL; 692 PedConstraint* user_constraint; 693 PedConstraint* dev_constraint; 694 PedConstraint* final_constraint; 695 char* peek_word; 696 char* part_name = NULL; 697 char *start_usr = NULL, *end_usr = NULL; 698 char *start_sol = NULL, *end_sol = NULL; 699 700 disk = ped_disk_new (*dev); 701 if (!disk) 702 goto error; 703 704 if (!ped_disk_type_check_feature (disk->type, PED_DISK_TYPE_EXTENDED)) { 705 part_type = PED_PARTITION_NORMAL; 706 } else { 707 if (!command_line_get_part_type (_("Partition type?"), 708 disk, &part_type)) 709 goto error_destroy_disk; 710 } 711 712 if (ped_disk_type_check_feature (disk->type, 713 PED_DISK_TYPE_PARTITION_NAME)) 714 part_name = command_line_get_word (_("Partition name?"), 715 "", NULL, 1); 716 717 peek_word = command_line_peek_word (); 718 if (part_type == PED_PARTITION_EXTENDED 719 || (peek_word && isdigit (peek_word[0]))) { 720 fs_type = NULL; 721 } else { 722 if (!command_line_get_fs_type (_("File system type?"), 723 &fs_type)) 724 goto error_destroy_disk; 725 } 726 if (peek_word) 727 ped_free (peek_word); 728 729 if (!command_line_get_sector (_("Start?"), *dev, &start, &range_start)) 730 goto error_destroy_disk; 731 if (!command_line_get_sector (_("End?"), *dev, &end, &range_end)) 732 goto error_destroy_disk; 733 734 /* processing starts here */ 735 part = ped_partition_new (disk, part_type, fs_type, start, end); 736 if (!part) 737 goto error_destroy_disk; 738 739 snap_to_boundaries (&part->geom, NULL, disk, range_start, range_end); 740 741 /* create constraints */ 742 user_constraint = constraint_from_start_end (*dev, range_start, 743 range_end); 744 PED_ASSERT (user_constraint != NULL, return 0); 745 746 dev_constraint = ped_device_get_constraint (*dev); 747 PED_ASSERT (dev_constraint != NULL, return 0); 748 749 final_constraint = ped_constraint_intersect (user_constraint, 750 dev_constraint); 751 if (!final_constraint) 752 goto error_destroy_simple_constraints; 753 754 /* subject to partition constraint */ 755 ped_exception_fetch_all(); 756 if (!ped_disk_add_partition (disk, part, final_constraint)) { 757 ped_exception_leave_all(); 758 759 if (ped_disk_add_partition (disk, part, 760 ped_constraint_any (*dev))) { 761 start_usr = ped_unit_format (*dev, start); 762 end_usr = ped_unit_format (*dev, end); 763 start_sol = ped_unit_format (*dev, part->geom.start); 764 end_sol = ped_unit_format (*dev, part->geom.end); 765 766 switch (ped_exception_throw ( 767 PED_EXCEPTION_WARNING, 768 PED_EXCEPTION_YES_NO, 769 _("You requested a partition from %s to %s.\n" 770 "The closest location we can manage is " 771 "%s to %s. " 772 "Is this still acceptable to you?"), 773 start_usr, end_usr, start_sol, end_sol)) 774 { 775 case PED_EXCEPTION_YES: 776 /* all is well in this state */ 777 break; 778 case PED_EXCEPTION_NO: 779 case PED_EXCEPTION_UNHANDLED: 780 default: 781 /* undo partition addition */ 782 goto error_remove_part; 783 } 784 } else { 785 goto error_remove_part; 786 } 787 } else { 788 ped_exception_leave_all(); 789 } 790 ped_exception_catch(); 791 792 /* set minor attributes */ 793 if (part_name) 794 PED_ASSERT (ped_partition_set_name (part, part_name), return 0); 795 if (!ped_partition_set_system (part, fs_type)) 796 goto error_destroy_disk; 797 if (ped_partition_is_flag_available (part, PED_PARTITION_LBA)) 798 ped_partition_set_flag (part, PED_PARTITION_LBA, 1); 799 800 if (!ped_disk_commit (disk)) 801 goto error_destroy_disk; 802 803 /* clean up */ 804 ped_constraint_destroy (final_constraint); 805 ped_constraint_destroy (user_constraint); 806 ped_constraint_destroy (dev_constraint); 807 808 ped_disk_destroy (disk); 809 810 if (range_start != NULL) 811 ped_geometry_destroy (range_start); 812 if (range_end != NULL) 813 ped_geometry_destroy (range_end); 814 815 if (start_usr != NULL) 816 ped_free (start_usr); 817 if (end_usr != NULL) 818 ped_free (end_usr); 819 if (start_sol != NULL) 820 ped_free (start_sol); 821 if (end_sol != NULL) 822 ped_free (end_sol); 823 824 if ((*dev)->type != PED_DEVICE_FILE) 825 disk_is_modified = 1; 826 827 return 1; 828 829error_remove_part: 830 ped_disk_remove_partition (disk, part); 831 ped_constraint_destroy (final_constraint); 832error_destroy_simple_constraints: 833 ped_constraint_destroy (user_constraint); 834 ped_constraint_destroy (dev_constraint); 835 ped_partition_destroy (part); 836error_destroy_disk: 837 ped_disk_destroy (disk); 838error: 839 if (range_start != NULL) 840 ped_geometry_destroy (range_start); 841 if (range_end != NULL) 842 ped_geometry_destroy (range_end); 843 844 if (start_usr != NULL) 845 ped_free (start_usr); 846 if (end_usr != NULL) 847 ped_free (end_usr); 848 if (start_sol != NULL) 849 ped_free (start_sol); 850 if (end_sol != NULL) 851 ped_free (end_sol); 852 853 return 0; 854} 855 856static int 857do_mkpartfs (PedDevice** dev) 858{ 859 PedDisk* disk; 860 PedPartition* part; 861 PedPartitionType part_type; 862 const PedFileSystemType* fs_type = ped_file_system_type_get ("ext2"); 863 PedSector start = 0, end = 0; 864 PedGeometry *range_start = NULL, *range_end = NULL; 865 PedConstraint* user_constraint; 866 PedConstraint* dev_constraint; 867 PedConstraint* final_constraint; 868 PedFileSystem* fs; 869 char* part_name = NULL; 870 char *start_usr = NULL, *end_usr = NULL; 871 char *start_sol = NULL, *end_sol = NULL; 872 873 disk = ped_disk_new (*dev); 874 if (!disk) 875 goto error; 876 877 if (!ped_disk_type_check_feature (disk->type, PED_DISK_TYPE_EXTENDED)) { 878 part_type = PED_PARTITION_NORMAL; 879 } else { 880 if (!command_line_get_part_type (_("Partition type?"), 881 disk, &part_type)) 882 goto error_destroy_disk; 883 } 884 885 if (ped_disk_type_check_feature (disk->type, 886 PED_DISK_TYPE_PARTITION_NAME)) 887 part_name = command_line_get_word (_("Partition name?"), 888 "", NULL, 1); 889 890 if (part_type == PED_PARTITION_EXTENDED) { 891 ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, 892 _("An extended partition cannot hold a file system. " 893 "Did you want mkpart?")); 894 goto error_destroy_disk; 895 } 896 897 if (!command_line_get_fs_type (_("File system type?"), &fs_type)) 898 goto error_destroy_disk; 899 if (!command_line_get_sector (_("Start?"), *dev, &start, 900 &range_start)) 901 goto error_destroy_disk; 902 if (!command_line_get_sector (_("End?"), *dev, &end, &range_end)) 903 goto error_destroy_disk; 904 905 /* attempt to create the partition now */ 906 part = ped_partition_new (disk, part_type, fs_type, start, end); 907 if (!part) 908 goto error_destroy_disk; 909 910 snap_to_boundaries (&part->geom, NULL, disk, range_start, range_end); 911 912 /* create constraints */ 913 user_constraint = constraint_from_start_end (*dev, range_start, 914 range_end); 915 PED_ASSERT (user_constraint != NULL, return 0); 916 917 dev_constraint = ped_device_get_constraint (*dev); 918 PED_ASSERT (dev_constraint != NULL, return 0); 919 920 final_constraint = ped_constraint_intersect (user_constraint, 921 dev_constraint); 922 if (!final_constraint) 923 goto error_destroy_simple_constraints; 924 925 /* subject to partition constraint */ 926 ped_exception_fetch_all(); 927 if (!ped_disk_add_partition (disk, part, final_constraint)) { 928 ped_exception_leave_all(); 929 930 if (ped_disk_add_partition (disk, part, 931 ped_constraint_any (*dev))) { 932 start_usr = ped_unit_format (*dev, start); 933 end_usr = ped_unit_format (*dev, end); 934 start_sol = ped_unit_format (*dev, part->geom.start); 935 end_sol = ped_unit_format (*dev, part->geom.end); 936 937 switch (ped_exception_throw ( 938 PED_EXCEPTION_WARNING, 939 PED_EXCEPTION_YES_NO, 940 _("You requested a partition from %s to %s.\n" 941 "The closest location we can manage is " 942 "%s to %s. " 943 "Is this still acceptable to you?"), 944 start_usr, end_usr, start_sol, end_sol)) { 945 case PED_EXCEPTION_YES: 946 /* all is well in this state */ 947 break; 948 case PED_EXCEPTION_NO: 949 case PED_EXCEPTION_UNHANDLED: 950 default: 951 /* undo partition addition */ 952 goto error_remove_part; 953 } 954 } else { 955 goto error_remove_part; 956 } 957 } else { 958 ped_exception_leave_all(); 959 } 960 ped_exception_catch(); 961 962 /* set LBA flag automatically if available */ 963 if (ped_partition_is_flag_available (part, PED_PARTITION_LBA)) 964 ped_partition_set_flag (part, PED_PARTITION_LBA, 1); 965 966 /* fs creation */ 967 fs = ped_file_system_create (&part->geom, fs_type, g_timer); 968 if (!fs) 969 goto error_destroy_disk; 970 ped_file_system_close (fs); 971 972 if (!ped_partition_set_system (part, fs_type)) 973 goto error_destroy_disk; 974 975 if (!ped_disk_commit (disk)) 976 goto error_destroy_disk; 977 978 /* clean up */ 979 ped_constraint_destroy (final_constraint); 980 ped_constraint_destroy (user_constraint); 981 ped_constraint_destroy (dev_constraint); 982 983 ped_disk_destroy (disk); 984 985 if (range_start != NULL) 986 ped_geometry_destroy (range_start); 987 if (range_end != NULL) 988 ped_geometry_destroy (range_end); 989 990 if (start_usr != NULL) 991 ped_free (start_usr); 992 if (end_usr != NULL) 993 ped_free (end_usr); 994 if (start_sol != NULL) 995 ped_free (start_sol); 996 if (end_sol != NULL) 997 ped_free (end_sol); 998 999 if ((*dev)->type != PED_DEVICE_FILE) 1000 disk_is_modified = 1; 1001 1002 return 1; 1003 1004error_remove_part: 1005 ped_disk_remove_partition (disk, part); 1006 ped_constraint_destroy (final_constraint); 1007error_destroy_simple_constraints: 1008 ped_constraint_destroy (user_constraint); 1009 ped_constraint_destroy (dev_constraint); 1010 ped_partition_destroy (part); 1011error_destroy_disk: 1012 ped_disk_destroy (disk); 1013error: 1014 if (range_start != NULL) 1015 ped_geometry_destroy (range_start); 1016 if (range_end != NULL) 1017 ped_geometry_destroy (range_end); 1018 1019 if (start_usr != NULL) 1020 ped_free (start_usr); 1021 if (end_usr != NULL) 1022 ped_free (end_usr); 1023 if (start_sol != NULL) 1024 ped_free (start_sol); 1025 if (end_sol != NULL) 1026 ped_free (end_sol); 1027 1028 return 0; 1029} 1030 1031static int 1032do_move (PedDevice** dev) 1033{ 1034 PedDisk* disk; 1035 PedPartition* part = NULL; 1036 PedFileSystem* fs; 1037 PedFileSystem* fs_copy; 1038 PedConstraint* constraint; 1039 PedSector start = 0, end = 0; 1040 PedGeometry *range_start = NULL, *range_end = NULL; 1041 PedGeometry old_geom, new_geom; 1042 1043 disk = ped_disk_new (*dev); 1044 if (!disk) 1045 goto error; 1046 1047 if (!command_line_get_partition (_("Partition number?"), disk, &part)) 1048 goto error_destroy_disk; 1049 if (!_partition_warn_busy (part)) 1050 goto error_destroy_disk; 1051 if (part->type == PED_PARTITION_EXTENDED) { 1052 ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, 1053 _("Can't move an extended partition.")); 1054 goto error_destroy_disk; 1055 } 1056 old_geom = part->geom; 1057 fs = ped_file_system_open (&old_geom); 1058 if (!fs) 1059 goto error_destroy_disk; 1060 1061 /* get new target */ 1062 if (!command_line_get_sector (_("Start?"), *dev, &start, &range_start)) 1063 goto error_close_fs; 1064 end = start + old_geom.length - 1; 1065 if (!command_line_get_sector (_("End?"), *dev, &end, &range_end)) 1066 goto error_close_fs; 1067 1068 /* set / test on "disk" */ 1069 if (!ped_geometry_init (&new_geom, *dev, start, end - start + 1)) 1070 goto error_close_fs; 1071 snap_to_boundaries (&new_geom, NULL, disk, range_start, range_end); 1072 1073 constraint = constraint_intersect_and_destroy ( 1074 ped_file_system_get_copy_constraint (fs, *dev), 1075 constraint_from_start_end(*dev,range_start,range_end)); 1076 if (!ped_disk_set_partition_geom (disk, part, constraint, 1077 new_geom.start, new_geom.end)) 1078 goto error_destroy_constraint; 1079 ped_constraint_destroy (constraint); 1080 if (ped_geometry_test_overlap (&old_geom, &part->geom)) { 1081 ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, 1082 _("Can't move a partition onto itself. Try using " 1083 "resize, perhaps?")); 1084 goto error_close_fs; 1085 } 1086 1087 /* do the move */ 1088 fs_copy = ped_file_system_copy (fs, &part->geom, g_timer); 1089 if (!fs_copy) 1090 goto error_close_fs; 1091 ped_file_system_close (fs_copy); 1092 ped_file_system_close (fs); 1093 if (!ped_disk_commit (disk)) 1094 goto error_destroy_disk; 1095 ped_disk_destroy (disk); 1096 if (range_start != NULL) 1097 ped_geometry_destroy (range_start); 1098 if (range_end != NULL) 1099 ped_geometry_destroy (range_end); 1100 1101 if ((*dev)->type != PED_DEVICE_FILE) 1102 disk_is_modified = 1; 1103 1104 return 1; 1105 1106error_destroy_constraint: 1107 ped_constraint_destroy (constraint); 1108error_close_fs: 1109 ped_file_system_close (fs); 1110error_destroy_disk: 1111 ped_disk_destroy (disk); 1112error: 1113 if (range_start != NULL) 1114 ped_geometry_destroy (range_start); 1115 if (range_end != NULL) 1116 ped_geometry_destroy (range_end); 1117 return 0; 1118} 1119 1120static int 1121do_name (PedDevice** dev) 1122{ 1123 PedDisk* disk; 1124 PedPartition* part = NULL; 1125 char* name; 1126 1127 disk = ped_disk_new (*dev); 1128 if (!disk) 1129 goto error; 1130 1131 if (!command_line_get_partition (_("Partition number?"), disk, &part)) 1132 goto error_destroy_disk; 1133 1134 name = command_line_get_word (_("Partition name?"), 1135 ped_partition_get_name (part), NULL, 0); 1136 if (!name) 1137 goto error_destroy_disk; 1138 if (!ped_partition_set_name (part, name)) 1139 goto error_free_name; 1140 free (name); 1141 1142 if (!ped_disk_commit (disk)) 1143 goto error_destroy_disk; 1144 ped_disk_destroy (disk); 1145 return 1; 1146 1147error_free_name: 1148 free (name); 1149error_destroy_disk: 1150 ped_disk_destroy (disk); 1151error: 1152 return 0; 1153} 1154 1155static char* 1156partition_print_flags (PedPartition* part) 1157{ 1158 PedPartitionFlag flag; 1159 int first_flag; 1160 const char* name; 1161 char* res = ped_malloc(1); 1162 void* _res = res; 1163 1164 *res = '\0'; 1165 1166 first_flag = 1; 1167 for (flag = ped_partition_flag_next (0); flag; 1168 flag = ped_partition_flag_next (flag)) { 1169 if (ped_partition_get_flag (part, flag)) { 1170 if (first_flag) 1171 first_flag = 0; 1172 else { 1173 _res = res; 1174 ped_realloc (&_res, strlen (res) 1175 + 1 + 2); 1176 res = _res; 1177 strncat (res, ", ", 2); 1178 } 1179 1180 name = _(ped_partition_flag_get_name (flag)); 1181 _res = res; 1182 ped_realloc (&_res, strlen (res) + 1 1183 + strlen (name)); 1184 res = _res; 1185 strncat (res, name, 21); 1186 } 1187 } 1188 1189 return res; 1190} 1191 1192/* Prints a sector out, first in compact form, and then with a percentage. 1193 * Eg: 32Gb (40%) 1194 */ 1195static void 1196print_sector_compact_and_percent (PedSector sector, PedDevice* dev) 1197{ 1198 char* compact; 1199 char* percent; 1200 1201 if (ped_unit_get_default() == PED_UNIT_PERCENT) 1202 compact = ped_unit_format (dev, sector); 1203 else 1204 compact = ped_unit_format_custom (dev, sector, 1205 PED_UNIT_COMPACT); 1206 1207 percent = ped_unit_format_custom (dev, sector, PED_UNIT_PERCENT); 1208 1209 printf ("%s (%s)\n", compact, percent); 1210 1211 ped_free (compact); 1212 ped_free (percent); 1213} 1214 1215static int 1216partition_print (PedPartition* part) 1217{ 1218 PedFileSystem* fs; 1219 PedConstraint* resize_constraint; 1220 char* flags; 1221 1222 fs = ped_file_system_open (&part->geom); 1223 if (!fs) 1224 return 1; 1225 1226 putchar ('\n'); 1227 1228 flags = partition_print_flags (part); 1229 1230 printf (_("Minor: %d\n"), part->num); 1231 printf (_("Flags: %s\n"), flags); 1232 printf (_("File System: %s\n"), fs->type->name); 1233 fputs (_("Size: "), stdout); 1234 print_sector_compact_and_percent (part->geom.length, part->geom.dev); 1235 1236 resize_constraint = ped_file_system_get_resize_constraint (fs); 1237 if (resize_constraint) { 1238 fputs (_("Minimum size: "), stdout); 1239 print_sector_compact_and_percent (resize_constraint->min_size, 1240 part->geom.dev); 1241 fputs (_("Maximum size: "), stdout); 1242 print_sector_compact_and_percent (resize_constraint->max_size, 1243 part->geom.dev); 1244 ped_constraint_destroy (resize_constraint); 1245 } 1246 1247 putchar ('\n'); 1248 1249 ped_free (flags); 1250 ped_file_system_close (fs); 1251 1252 return 1; 1253} 1254 1255static int 1256do_print (PedDevice** dev) 1257{ 1258 PedUnit default_unit; 1259 PedDisk* disk; 1260 Table* table; 1261 int has_extended; 1262 int has_name; 1263 int has_devices_arg = 0; 1264 int has_free_arg = 0; 1265 int has_list_arg = 0; 1266 int has_num_arg = 0; 1267 char* transport[13] = {"unknown", "scsi", "ide", "dac960", 1268 "cpqarray", "file", "ataraid", "i2o", 1269 "ubd", "dasd", "viodasd", "sx8", "dm"}; 1270 char* peek_word; 1271 char* start; 1272 char* end; 1273 char* size; 1274 const char* name; 1275 char* tmp; 1276 wchar_t* table_rendered; 1277 1278 disk = ped_disk_new (*dev); 1279 if (!disk) 1280 goto error; 1281 1282 peek_word = command_line_peek_word (); 1283 if (peek_word) { 1284 if (strncmp (peek_word, "devices", 7) == 0) { 1285 command_line_pop_word(); 1286 has_devices_arg = 1; 1287 } 1288 else if (strncmp (peek_word, "free", 4) == 0) { 1289 command_line_pop_word (); 1290 has_free_arg = 1; 1291 } 1292 else if (strncmp (peek_word, "list", 4) == 0 || 1293 strncmp (peek_word, "all", 3) == 0) { 1294 command_line_pop_word(); 1295 has_list_arg = 1; 1296 } 1297 else 1298 has_num_arg = isdigit(peek_word[0]); 1299 1300 ped_free (peek_word); 1301 } 1302 1303 if (has_devices_arg) { 1304 char* dev_name; 1305 PedDevice* current_dev = NULL; 1306 1307 ped_device_probe_all(); 1308 1309 while ((current_dev = ped_device_get_next(current_dev))) { 1310 end = ped_unit_format_byte (current_dev, 1311 current_dev->length 1312 * current_dev->sector_size); 1313 printf ("%s (%s)\n", current_dev->path, end); 1314 ped_free (end); 1315 } 1316 1317 dev_name = xstrdup ((*dev)->path); 1318 ped_device_free_all (); 1319 1320 *dev = ped_device_get (dev_name); 1321 if (!*dev) 1322 return 0; 1323 if (!ped_device_open (*dev)) 1324 return 0; 1325 1326 ped_free (dev_name); 1327 1328 return 1; 1329 } 1330 1331 else if (has_list_arg) 1332 return _print_list (); 1333 1334 else if (has_num_arg) { 1335 PedPartition* part = NULL; 1336 int status = 0; 1337 if (command_line_get_partition ("", disk, &part)) 1338 status = partition_print (part); 1339 ped_disk_destroy (disk); 1340 return status; 1341 } 1342 1343 start = ped_unit_format (*dev, 0); 1344 default_unit = ped_unit_get_default (); 1345 end = ped_unit_format_byte (*dev, (*dev)->length * (*dev)->sector_size 1346 - (default_unit == PED_UNIT_CHS || 1347 default_unit == PED_UNIT_CYLINDER)); 1348 1349 if (opt_machine_mode) { 1350 switch (default_unit) { 1351 case PED_UNIT_CHS: puts ("CHS;"); 1352 break; 1353 case PED_UNIT_CYLINDER: puts ("CYL;"); 1354 break; 1355 default: puts ("BYT;"); 1356 break; 1357 1358 } 1359 printf ("%s:%s:%s:%lld:%lld:%s:%s;\n", 1360 (*dev)->path, end, transport[(*dev)->type], 1361 (*dev)->sector_size, (*dev)->phys_sector_size, 1362 disk->type->name, (*dev)->model); 1363 } else { 1364 printf (_("Model: %s (%s)\n"), 1365 (*dev)->model, transport[(*dev)->type]); 1366 printf (_("Disk %s: %s\n"), (*dev)->path, end); 1367 printf (_("Sector size (logical/physical): %lldB/%lldB\n"), 1368 (*dev)->sector_size, (*dev)->phys_sector_size); 1369 } 1370 1371 ped_free (start); 1372 ped_free (end); 1373 1374 if (ped_unit_get_default () == PED_UNIT_CHS 1375 || ped_unit_get_default () == PED_UNIT_CYLINDER) { 1376 PedCHSGeometry* chs = &(*dev)->bios_geom; 1377 char* cyl_size = ped_unit_format_custom (*dev, 1378 chs->heads * chs->sectors, 1379 PED_UNIT_KILOBYTE); 1380 1381 if (opt_machine_mode) { 1382 printf ("%d:%d:%d:%s;\n", 1383 chs->cylinders, chs->heads, chs->sectors, cyl_size); 1384 } else { 1385 printf (_("BIOS cylinder,head,sector geometry: %d,%d,%d. " 1386 "Each cylinder is %s.\n"), 1387 chs->cylinders, chs->heads, chs->sectors, cyl_size); 1388 } 1389 1390 ped_free (cyl_size); 1391 } 1392 1393 if (!opt_machine_mode) { 1394 printf (_("Partition Table: %s\n"), disk->type->name); 1395 putchar ('\n'); 1396 } 1397 1398 has_extended = ped_disk_type_check_feature (disk->type, 1399 PED_DISK_TYPE_EXTENDED); 1400 has_name = ped_disk_type_check_feature (disk->type, 1401 PED_DISK_TYPE_PARTITION_NAME); 1402 1403 1404 PedPartition* part; 1405 if (!opt_machine_mode) { 1406 StrList *row1; 1407 1408 if (ped_unit_get_default() == PED_UNIT_CHS) { 1409 row1 = str_list_create (_("Number"), _("Start"), 1410 _("End"), NULL); 1411 } else { 1412 row1 = str_list_create (_("Number"), _("Start"), 1413 _("End"), _("Size"), NULL); 1414 } 1415 1416 if (has_extended) 1417 str_list_append (row1, _("Type")); 1418 1419 str_list_append (row1, _("File system")); 1420 1421 if (has_name) 1422 str_list_append (row1, _("Name")); 1423 1424 str_list_append (row1, _("Flags")); 1425 1426 1427 table = table_new (str_list_length(row1)); 1428 1429 table_add_row_from_strlist (table, row1); 1430 1431 for (part = ped_disk_next_partition (disk, NULL); part; 1432 part = ped_disk_next_partition (disk, part)) { 1433 1434 if ((!has_free_arg && !ped_partition_is_active(part)) || 1435 part->type & PED_PARTITION_METADATA) 1436 continue; 1437 1438 tmp = ped_malloc (4); 1439 1440 if (part->num >= 0) 1441 sprintf (tmp, "%2d ", part->num); 1442 else 1443 sprintf (tmp, "%2s ", ""); 1444 1445 StrList *row = str_list_create (tmp, NULL); 1446 1447 start = ped_unit_format (*dev, part->geom.start); 1448 end = ped_unit_format_byte ( 1449 *dev, 1450 (part->geom.end + 1) * (*dev)->sector_size - 1); 1451 size = ped_unit_format (*dev, part->geom.length); 1452 if (ped_unit_get_default() == PED_UNIT_CHS) { 1453 str_list_append (row, start); 1454 str_list_append (row, end); 1455 } else { 1456 str_list_append (row, start); 1457 str_list_append (row, end); 1458 str_list_append (row, size); 1459 } 1460 1461 if (!(part->type & PED_PARTITION_FREESPACE)) { 1462 if (has_extended) { 1463 name = ped_partition_type_get_name (part->type); 1464 str_list_append (row, name); 1465 } 1466 1467 str_list_append (row, part->fs_type ? 1468 part->fs_type->name : ""); 1469 1470 if (has_name) { 1471 name = ped_partition_get_name (part); 1472 str_list_append (row, name); 1473 } 1474 1475 str_list_append (row, partition_print_flags (part)); 1476 } else { 1477 if (has_extended) 1478 str_list_append (row, ""); 1479 str_list_append (row, _("Free Space")); 1480 if (has_name) 1481 str_list_append (row, ""); 1482 str_list_append (row, ""); 1483 } 1484 1485 //PED_ASSERT (row.cols == caption.cols) 1486 table_add_row_from_strlist (table, row); 1487 str_list_destroy (row); 1488 } 1489 1490 table_rendered = table_render (table); 1491#ifdef ENABLE_NLS 1492 printf("%ls\n", table_rendered); 1493#else 1494 printf("%s\n", table_rendered); 1495#endif 1496 ped_free (table_rendered); 1497 table_destroy (table); 1498 str_list_destroy (row1); 1499 1500 } else { 1501 1502 for (part = ped_disk_next_partition (disk, NULL); part; 1503 part = ped_disk_next_partition (disk, part)) { 1504 1505 if ((!has_free_arg && !ped_partition_is_active(part)) || 1506 part->type & PED_PARTITION_METADATA) 1507 continue; 1508 1509 if (part->num >= 0) 1510 printf ("%d:", part->num); 1511 else 1512 fputs ("1:", stdout); 1513 1514 printf ("%s:", ped_unit_format (*dev, part->geom.start)); 1515 printf ("%s:", ped_unit_format_byte ( 1516 *dev, 1517 (part->geom.end + 1) * 1518 (*dev)->sector_size - 1)); 1519 1520 if (ped_unit_get_default() != PED_UNIT_CHS) 1521 printf ("%s:", ped_unit_format (*dev, 1522 part->geom.length)); 1523 1524 if (!(part->type & PED_PARTITION_FREESPACE)) { 1525 1526 if (part->fs_type) 1527 printf ("%s:", part->fs_type->name); 1528 else 1529 putchar (':'); 1530 1531 if (has_name) 1532 printf ("%s:", _(ped_partition_get_name (part))); 1533 else 1534 putchar (':'); 1535 1536 printf ("%s;\n", partition_print_flags (part)); 1537 1538 } else { 1539 puts ("free;"); 1540 } 1541 } 1542 } 1543 1544 ped_disk_destroy (disk); 1545 1546 return 1; 1547 1548 ped_disk_destroy (disk); 1549error: 1550 return 0; 1551} 1552 1553static int 1554_print_list () 1555{ 1556 PedDevice *current_dev = NULL; 1557 1558 ped_device_probe_all(); 1559 1560 while ((current_dev = ped_device_get_next(current_dev))) { 1561 do_print (¤t_dev); 1562 putchar ('\n'); 1563 } 1564 1565 return 1; 1566} 1567 1568static int 1569do_quit (PedDevice** dev) 1570{ 1571 _done (*dev); 1572 exit (0); 1573} 1574 1575static PedPartitionType 1576_disk_get_part_type_for_sector (PedDisk* disk, PedSector sector) 1577{ 1578 PedPartition* extended; 1579 1580 extended = ped_disk_extended_partition (disk); 1581 if (!extended 1582 || !ped_geometry_test_sector_inside (&extended->geom, sector)) 1583 return 0; 1584 1585 return PED_PARTITION_LOGICAL; 1586} 1587 1588/* This function checks if "part" contains a file system, and returs 1589 * 0 if either no file system was found, or the user declined to add it. 1590 * 1 if a file system was found, and the user chose to add it. 1591 * -1 if the user chose to cancel the entire search. 1592 */ 1593static int 1594_rescue_add_partition (PedPartition* part) 1595{ 1596 const PedFileSystemType* fs_type; 1597 PedGeometry* probed; 1598 PedExceptionOption ex_opt; 1599 PedConstraint* constraint; 1600 char* found_start; 1601 char* found_end; 1602 1603 fs_type = ped_file_system_probe (&part->geom); 1604 if (!fs_type) 1605 return 0; 1606 probed = ped_file_system_probe_specific (fs_type, &part->geom); 1607 if (!probed) 1608 return 0; 1609 1610 if (!ped_geometry_test_inside (&part->geom, probed)) { 1611 ped_geometry_destroy (probed); 1612 return 0; 1613 } 1614 1615 constraint = ped_constraint_exact (probed); 1616 if (!ped_disk_set_partition_geom (part->disk, part, constraint, 1617 probed->start, probed->end)) { 1618 ped_constraint_destroy (constraint); 1619 return 0; 1620 } 1621 ped_constraint_destroy (constraint); 1622 1623 found_start = ped_unit_format (probed->dev, probed->start); 1624 found_end = ped_unit_format (probed->dev, probed->end); 1625 ex_opt = ped_exception_throw ( 1626 PED_EXCEPTION_INFORMATION, 1627 PED_EXCEPTION_YES_NO_CANCEL, 1628 _("A %s %s partition was found at %s -> %s. " 1629 "Do you want to add it to the partition table?"), 1630 fs_type->name, ped_partition_type_get_name (part->type), 1631 found_start, found_end); 1632 ped_geometry_destroy (probed); 1633 ped_free (found_start); 1634 ped_free (found_end); 1635 1636 switch (ex_opt) { 1637 case PED_EXCEPTION_CANCEL: return -1; 1638 case PED_EXCEPTION_NO: return 0; 1639 default: break; 1640 } 1641 1642 ped_partition_set_system (part, fs_type); 1643 ped_disk_commit (part->disk); 1644 return 1; 1645} 1646 1647/* hack: we only iterate through the start, since most (all) fs's have their 1648 * superblocks at the start. We'll need to change this if we generalize 1649 * for RAID, or something... 1650 */ 1651static int 1652_rescue_pass (PedDisk* disk, PedGeometry* start_range, PedGeometry* end_range) 1653{ 1654 PedSector start; 1655 PedGeometry start_geom_exact; 1656 PedGeometry entire_dev; 1657 PedConstraint constraint; 1658 PedPartition* part; 1659 PedPartitionType part_type; 1660 1661 part_type = _disk_get_part_type_for_sector ( 1662 disk, (start_range->start + end_range->end) / 2); 1663 1664 ped_geometry_init (&entire_dev, disk->dev, 0, disk->dev->length); 1665 1666 ped_timer_reset (g_timer); 1667 ped_timer_set_state_name (g_timer, _("searching for file systems")); 1668 for (start = start_range->start; start <= start_range->end; start++) { 1669 ped_timer_update (g_timer, 1.0 * (start - start_range->start) 1670 / start_range->length); 1671 1672 ped_geometry_init (&start_geom_exact, disk->dev, start, 1); 1673 ped_constraint_init ( 1674 &constraint, ped_alignment_any, ped_alignment_any, 1675 &start_geom_exact, &entire_dev, 1676 1, disk->dev->length); 1677 part = ped_partition_new (disk, part_type, NULL, start, 1678 end_range->end); 1679 if (!part) { 1680 ped_constraint_done (&constraint); 1681 continue; 1682 } 1683 1684 ped_exception_fetch_all (); 1685 if (ped_disk_add_partition (disk, part, &constraint)) { 1686 ped_exception_leave_all (); 1687 switch (_rescue_add_partition (part)) { 1688 case 1: 1689 ped_constraint_done (&constraint); 1690 return 1; 1691 1692 case 0: 1693 ped_disk_remove_partition (disk, part); 1694 break; 1695 1696 case -1: 1697 goto error_remove_partition; 1698 } 1699 } else { 1700 ped_exception_leave_all (); 1701 } 1702 ped_partition_destroy (part); 1703 ped_constraint_done (&constraint); 1704 } 1705 ped_timer_update (g_timer, 1.0); 1706 1707 return 1; 1708 1709error_remove_partition: 1710 ped_disk_remove_partition (disk, part); 1711 ped_partition_destroy (part); 1712 ped_constraint_done (&constraint); 1713 return 0; 1714} 1715 1716static int 1717do_rescue (PedDevice** dev) 1718{ 1719 PedDisk* disk; 1720 PedSector start = 0, end = 0; 1721 PedSector fuzz; 1722 PedGeometry probe_start_region; 1723 PedGeometry probe_end_region; 1724 1725 disk = ped_disk_new (*dev); 1726 if (!disk) 1727 goto error; 1728 1729 if (!command_line_get_sector (_("Start?"), *dev, &start, NULL)) 1730 goto error_destroy_disk; 1731 if (!command_line_get_sector (_("End?"), *dev, &end, NULL)) 1732 goto error_destroy_disk; 1733 1734 fuzz = PED_MAX (PED_MIN ((end - start) / 10, MEGABYTE_SECTORS(*dev)), 1735 MEGABYTE_SECTORS(*dev) * 16); 1736 1737 ped_geometry_init (&probe_start_region, *dev, 1738 PED_MAX(start - fuzz, 0), 1739 PED_MIN(2 * fuzz, (*dev)->length - (start - fuzz))); 1740 ped_geometry_init (&probe_end_region, *dev, 1741 PED_MAX(end - fuzz, 0), 1742 PED_MIN(2 * fuzz, (*dev)->length - (end - fuzz))); 1743 1744 if (!_rescue_pass (disk, &probe_start_region, &probe_end_region)) 1745 goto error_destroy_disk; 1746 1747 ped_disk_destroy (disk); 1748 1749 if ((*dev)->type != PED_DEVICE_FILE) 1750 disk_is_modified = 1; 1751 1752 return 1; 1753 1754error_destroy_disk: 1755 ped_disk_destroy (disk); 1756error: 1757 return 0; 1758} 1759 1760static int 1761do_resize (PedDevice** dev) 1762{ 1763 PedDisk *disk; 1764 PedPartition *part = NULL; 1765 PedFileSystem *fs; 1766 PedConstraint *constraint; 1767 PedSector start, end; 1768 PedGeometry *range_start = NULL, *range_end = NULL; 1769 PedGeometry new_geom; 1770 1771 disk = ped_disk_new (*dev); 1772 if (!disk) 1773 goto error; 1774 1775 if (!command_line_get_partition (_("Partition number?"), disk, &part)) 1776 goto error_destroy_disk; 1777 if (part->type != PED_PARTITION_EXTENDED) { 1778 if (!_partition_warn_busy (part)) 1779 goto error_destroy_disk; 1780 } 1781 1782 start = part->geom.start; 1783 end = part->geom.end; 1784 if (!command_line_get_sector (_("Start?"), *dev, &start, &range_start)) 1785 goto error_destroy_disk; 1786 if (!command_line_get_sector (_("End?"), *dev, &end, &range_end)) 1787 goto error_destroy_disk; 1788 1789 if (!ped_geometry_init (&new_geom, *dev, start, end - start + 1)) 1790 goto error_destroy_disk; 1791 snap_to_boundaries (&new_geom, &part->geom, disk, 1792 range_start, range_end); 1793 1794 if (part->type == PED_PARTITION_EXTENDED) { 1795 constraint = constraint_from_start_end (*dev, 1796 range_start, range_end); 1797 if (!ped_disk_set_partition_geom (disk, part, constraint, 1798 new_geom.start, new_geom.end)) 1799 goto error_destroy_constraint; 1800 ped_partition_set_system (part, NULL); 1801 } else { 1802 fs = ped_file_system_open (&part->geom); 1803 if (!fs) 1804 goto error_destroy_disk; 1805 constraint = constraint_intersect_and_destroy ( 1806 ped_file_system_get_resize_constraint (fs), 1807 constraint_from_start_end ( 1808 *dev, range_start, range_end)); 1809 if (!ped_disk_set_partition_geom (disk, part, constraint, 1810 new_geom.start, new_geom.end)) 1811 goto error_close_fs; 1812 if (!ped_file_system_resize (fs, &part->geom, g_timer)) 1813 goto error_close_fs; 1814 /* may have changed... eg fat16 -> fat32 */ 1815 ped_partition_set_system (part, fs->type); 1816 ped_file_system_close (fs); 1817 } 1818 1819 ped_disk_commit (disk); 1820 ped_constraint_destroy (constraint); 1821 ped_disk_destroy (disk); 1822 if (range_start != NULL) 1823 ped_geometry_destroy (range_start); 1824 if (range_end != NULL) 1825 ped_geometry_destroy (range_end); 1826 1827 if ((*dev)->type != PED_DEVICE_FILE) 1828 disk_is_modified = 1; 1829 1830 return 1; 1831 1832error_close_fs: 1833 ped_file_system_close (fs); 1834error_destroy_constraint: 1835 ped_constraint_destroy (constraint); 1836error_destroy_disk: 1837 ped_disk_destroy (disk); 1838error: 1839 if (range_start != NULL) 1840 ped_geometry_destroy (range_start); 1841 if (range_end != NULL) 1842 ped_geometry_destroy (range_end); 1843 return 0; 1844} 1845 1846static int 1847do_rm (PedDevice** dev) 1848{ 1849 PedDisk* disk; 1850 PedPartition* part = NULL; 1851 1852 disk = ped_disk_new (*dev); 1853 if (!disk) 1854 goto error; 1855 1856 if (!command_line_get_partition (_("Partition number?"), disk, &part)) 1857 goto error_destroy_disk; 1858 if (!_partition_warn_busy (part)) 1859 goto error_destroy_disk; 1860 1861 ped_disk_delete_partition (disk, part); 1862 ped_disk_commit (disk); 1863 ped_disk_destroy (disk); 1864 1865 if ((*dev)->type != PED_DEVICE_FILE) 1866 disk_is_modified = 1; 1867 1868 return 1; 1869 1870error_destroy_disk: 1871 ped_disk_destroy (disk); 1872error: 1873 return 0; 1874} 1875 1876static int 1877do_select (PedDevice** dev) 1878{ 1879 PedDevice* new_dev = *dev; 1880 1881 if (!command_line_get_device (_("New device?"), &new_dev)) 1882 return 0; 1883 if (!ped_device_open (new_dev)) 1884 return 0; 1885 1886 ped_device_close (*dev); 1887 *dev = new_dev; 1888 print_using_dev (*dev); 1889 return 1; 1890} 1891 1892static int 1893do_set (PedDevice** dev) 1894{ 1895 PedDisk* disk; 1896 PedPartition* part = NULL; 1897 PedPartitionFlag flag; 1898 int state; 1899 1900 disk = ped_disk_new (*dev); 1901 if (!disk) 1902 goto error; 1903 1904 if (!command_line_get_partition (_("Partition number?"), disk, &part)) 1905 goto error_destroy_disk; 1906 if (!command_line_get_part_flag (_("Flag to Invert?"), part, &flag)) 1907 goto error_destroy_disk; 1908 state = (ped_partition_get_flag (part, flag) == 0 ? 1 : 0); 1909 1910 if (!is_toggle_mode) { 1911 if (!command_line_get_state (_("New state?"), &state)) 1912 goto error_destroy_disk; 1913 } 1914 1915 if (!ped_partition_set_flag (part, flag, state)) 1916 goto error_destroy_disk; 1917 if (!ped_disk_commit (disk)) 1918 goto error_destroy_disk; 1919 ped_disk_destroy (disk); 1920 1921 if ((*dev)->type != PED_DEVICE_FILE) 1922 disk_is_modified = 1; 1923 1924 return 1; 1925 1926error_destroy_disk: 1927 ped_disk_destroy (disk); 1928error: 1929 return 0; 1930} 1931 1932static int 1933do_toggle (PedDevice **dev) 1934{ 1935 int result; 1936 1937 is_toggle_mode = 1; 1938 result = do_set (dev); 1939 is_toggle_mode = 0; 1940 1941 return result; 1942} 1943 1944static int 1945do_unit (PedDevice** dev) 1946{ 1947 PedUnit unit = ped_unit_get_default (); 1948 if (!command_line_get_unit (_("Unit?"), &unit)) 1949 return 0; 1950 ped_unit_set_default (unit); 1951 return 1; 1952} 1953 1954static int 1955do_version () 1956{ 1957 printf ("\n%s\n%s", 1958 prog_name, 1959 _(copyright_msg)); 1960 return 1; 1961} 1962 1963static void 1964_init_messages () 1965{ 1966 StrList* list; 1967 int first; 1968 PedFileSystemType* fs_type; 1969 PedDiskType* disk_type; 1970 PedPartitionFlag part_flag; 1971 PedUnit unit; 1972 1973/* flags */ 1974 first = 1; 1975 list = str_list_create (_(flag_msg_start), NULL); 1976 for (part_flag = ped_partition_flag_next (0); part_flag; 1977 part_flag = ped_partition_flag_next (part_flag)) { 1978 if (first) 1979 first = 0; 1980 else 1981 str_list_append (list, ", "); 1982 str_list_append (list, 1983 _(ped_partition_flag_get_name (part_flag))); 1984 } 1985 str_list_append (list, "\n"); 1986 1987 flag_msg = str_list_convert (list); 1988 str_list_destroy (list); 1989 1990/* units */ 1991 first = 1; 1992 list = str_list_create (_(unit_msg_start), NULL); 1993 for (unit = PED_UNIT_FIRST; unit <= PED_UNIT_LAST; unit++) { 1994 if (first) 1995 first = 0; 1996 else 1997 str_list_append (list, ", "); 1998 str_list_append (list, ped_unit_get_name (unit)); 1999 } 2000 str_list_append (list, "\n"); 2001 2002 unit_msg = str_list_convert (list); 2003 str_list_destroy (list); 2004 2005/* disk type */ 2006 list = str_list_create (_(label_type_msg_start), NULL); 2007 2008 first = 1; 2009 for (disk_type = ped_disk_type_get_next (NULL); 2010 disk_type; disk_type = ped_disk_type_get_next (disk_type)) { 2011 if (disk_type->ops->write == NULL) 2012 continue; 2013 2014 if (first) 2015 first = 0; 2016 else 2017 str_list_append (list, ", "); 2018 str_list_append (list, disk_type->name); 2019 } 2020 str_list_append (list, "\n"); 2021 2022 label_type_msg = str_list_convert (list); 2023 str_list_destroy (list); 2024 2025/* mkfs - file system types */ 2026 list = str_list_create (_(fs_type_msg_start), NULL); 2027 2028 first = 1; 2029 for (fs_type = ped_file_system_type_get_next (NULL); 2030 fs_type; fs_type = ped_file_system_type_get_next (fs_type)) { 2031 if (fs_type->ops->create == NULL) 2032 continue; 2033 2034 if (first) 2035 first = 0; 2036 else 2037 str_list_append (list, ", "); 2038 str_list_append (list, fs_type->name); 2039 } 2040 str_list_append (list, "\n"); 2041 2042 mkfs_fs_type_msg = str_list_convert (list); 2043 str_list_destroy (list); 2044 2045/* mkpart - file system types */ 2046 list = str_list_create (_(fs_type_msg_start), NULL); 2047 2048 first = 1; 2049 for (fs_type = ped_file_system_type_get_next (NULL); 2050 fs_type; fs_type = ped_file_system_type_get_next (fs_type)) { 2051 if (first) 2052 first = 0; 2053 else 2054 str_list_append (list, ", "); 2055 str_list_append (list, fs_type->name); 2056 } 2057 str_list_append (list, "\n"); 2058 2059 mkpart_fs_type_msg = str_list_convert (list); 2060 str_list_destroy (list); 2061 2062/* resize - file system types */ 2063 list = str_list_create (_(resize_msg_start), NULL); 2064 2065 first = 1; 2066 for (fs_type = ped_file_system_type_get_next (NULL); 2067 fs_type; fs_type = ped_file_system_type_get_next (fs_type)) { 2068 if (fs_type->ops->resize == NULL) 2069 continue; 2070 2071 if (first) 2072 first = 0; 2073 else 2074 str_list_append (list, ", "); 2075 str_list_append (list, fs_type->name); 2076 } 2077 str_list_append (list, "\n"); 2078 2079 resize_fs_type_msg = str_list_convert (list); 2080 str_list_destroy (list); 2081} 2082 2083static void 2084_done_messages () 2085{ 2086 free (flag_msg); 2087 free (mkfs_fs_type_msg); 2088 free (mkpart_fs_type_msg); 2089 free (resize_fs_type_msg); 2090 free (label_type_msg); 2091} 2092 2093static void 2094_init_commands () 2095{ 2096 command_register (commands, command_create ( 2097 str_list_create_unique ("check", _("check"), NULL), 2098 do_check, 2099 str_list_create ( 2100_("check NUMBER do a simple check on the file " 2101 "system"), 2102NULL), 2103 str_list_create (_(number_msg), NULL), 1)); 2104 2105 command_register (commands, command_create ( 2106 str_list_create_unique ("cp", _("cp"), NULL), 2107 do_cp, 2108 str_list_create ( 2109_("cp [FROM-DEVICE] FROM-NUMBER TO-NUMBER copy file system to another " 2110 "partition"), 2111NULL), 2112 str_list_create (_(number_msg), _(device_msg), NULL), 1)); 2113 2114 command_register (commands, command_create ( 2115 str_list_create_unique ("help", _("help"), NULL), 2116 do_help, 2117 str_list_create ( 2118_("help [COMMAND] print general help, or help " 2119 "on COMMAND"), 2120NULL), 2121 NULL, 1)); 2122 2123 command_register (commands, command_create ( 2124 str_list_create_unique ("mklabel", _("mklabel"), "mktable", _("mktable"), NULL), 2125 do_mklabel, 2126 str_list_create ( 2127_("mklabel,mktable LABEL-TYPE create a new disklabel " 2128 "(partition table)"), 2129NULL), 2130 str_list_create (label_type_msg, NULL), 1)); 2131 2132 command_register (commands, command_create ( 2133 str_list_create_unique ("mkfs", _("mkfs"), NULL), 2134 do_mkfs, 2135 str_list_create ( 2136_("mkfs NUMBER FS-TYPE make a FS-TYPE file " 2137 "system on partititon NUMBER"), 2138NULL), 2139 str_list_create (_(number_msg), _(mkfs_fs_type_msg), NULL), 1)); 2140 2141 command_register (commands, command_create ( 2142 str_list_create_unique ("mkpart", _("mkpart"), NULL), 2143 do_mkpart, 2144 str_list_create ( 2145_("mkpart PART-TYPE [FS-TYPE] START END make a partition"), 2146NULL), 2147 str_list_create (_(part_type_msg), 2148 _(mkpart_fs_type_msg), 2149 _(start_end_msg), 2150 "\n", 2151_("'mkpart' makes a partition without creating a new file system on the " 2152 "partition. FS-TYPE may be specified to set an appropriate partition ID.\n"), 2153NULL), 1)); 2154 2155 command_register (commands, command_create ( 2156 str_list_create_unique ("mkpartfs", _("mkpartfs"), NULL), 2157 do_mkpartfs, 2158 str_list_create ( 2159_("mkpartfs PART-TYPE FS-TYPE START END make a partition with a " 2160 "file system"), 2161NULL), 2162 str_list_create (_(part_type_msg), _(start_end_msg), NULL), 1)); 2163 2164command_register (commands, command_create ( 2165 str_list_create_unique ("move", _("move"), NULL), 2166 do_move, 2167 str_list_create ( 2168_("move NUMBER START END move partition NUMBER"), 2169NULL), 2170 str_list_create (_(number_msg), _(start_end_msg), NULL), 1)); 2171 2172command_register (commands, command_create ( 2173 str_list_create_unique ("name", _("name"), NULL), 2174 do_name, 2175 str_list_create ( 2176_("name NUMBER NAME name partition NUMBER as NAME"), 2177NULL), 2178 str_list_create (_(number_msg), _(name_msg), NULL), 1)); 2179 2180command_register (commands, command_create ( 2181 str_list_create_unique ("print", _("print"), NULL), 2182 do_print, 2183 str_list_create ( 2184_("print [devices|free|list,all|NUMBER] display the partition table, " 2185 "available devices, free space, all found partitions, or a particular " 2186 "partition"), 2187NULL), 2188 str_list_create ( 2189_("Without arguments, 'print' displays the entire partition table. However " 2190 "with the following arguments it performs various other actions.\n"), 2191_(" devices : display all active block devices\n"), 2192_(" free : display information about free unpartitioned space on the " 2193 "current block device\n"), 2194_(" list, all : display the partition tables of all active block devices\n"), 2195_(" NUMBER : display more detailed information about this particular " 2196 "partition\n"), 2197NULL), 1)); 2198 2199command_register (commands, command_create ( 2200 str_list_create_unique ("quit", _("quit"), NULL), 2201 do_quit, 2202 str_list_create ( 2203_("quit exit program"), 2204NULL), 2205 NULL, 1)); 2206 2207command_register (commands, command_create ( 2208 str_list_create_unique ("rescue", _("rescue"), NULL), 2209 do_rescue, 2210 str_list_create ( 2211_("rescue START END rescue a lost partition near " 2212"START and END"), 2213NULL), 2214 str_list_create (_(start_end_msg), NULL), 1)); 2215 2216command_register (commands, command_create ( 2217 str_list_create_unique ("resize", _("resize"), NULL), 2218 do_resize, 2219 str_list_create ( 2220_("resize NUMBER START END resize partition NUMBER and " 2221"its file system"), 2222NULL), 2223 str_list_create (_(number_msg), 2224 _(start_end_msg), 2225 _(resize_fs_type_msg), NULL), 1)); 2226 2227command_register (commands, command_create ( 2228 str_list_create_unique ("rm", _("rm"), NULL), 2229 do_rm, 2230 str_list_create ( 2231_("rm NUMBER delete partition NUMBER"), 2232NULL), 2233 str_list_create (_(number_msg), NULL), 1)); 2234 2235command_register (commands, command_create ( 2236 str_list_create_unique ("select", _("select"), NULL), 2237 do_select, 2238 str_list_create ( 2239_("select DEVICE choose the device to edit"), 2240NULL), 2241 str_list_create (_(device_msg), NULL), 1)); 2242 2243command_register (commands, command_create ( 2244 str_list_create_unique ("set", _("set"), NULL), 2245 do_set, 2246 str_list_create ( 2247_("set NUMBER FLAG STATE change the FLAG on partition " 2248 "NUMBER"), 2249NULL), 2250 str_list_create (_(number_msg), flag_msg, _(state_msg), NULL), 1)); 2251 2252command_register (commands, command_create ( 2253 str_list_create_unique ("toggle", _("toggle"), NULL), 2254 do_toggle, 2255 str_list_create ( 2256_("toggle [NUMBER [FLAG]] toggle the state of FLAG on " 2257 "partition NUMBER"), 2258NULL), 2259 str_list_create (_(number_msg), flag_msg, NULL), 1)); 2260 2261command_register (commands, command_create ( 2262 str_list_create_unique ("unit", _("unit"), NULL), 2263 do_unit, 2264 str_list_create ( 2265_("unit UNIT set the default unit to UNIT"), 2266NULL), 2267 str_list_create (unit_msg, NULL), 1)); 2268 2269command_register (commands, command_create ( 2270 str_list_create_unique ("version", _("version"), NULL), 2271 do_version, 2272 str_list_create ( 2273_("version display the version number " 2274"and copyright information of GNU Parted"), 2275NULL), 2276 str_list_create ( 2277_("'version' displays copyright and version information corresponding to this " 2278"copy of GNU Parted\n"), 2279NULL), 1)); 2280 2281} 2282 2283static void 2284_done_commands () 2285{ 2286Command** walk; 2287 2288for (walk = commands; *walk; walk++) { 2289 command_destroy (*walk); 2290 *walk = NULL; 2291} 2292} 2293 2294static void 2295_init_i18n () 2296{ 2297/* intialize i18n */ 2298#ifdef ENABLE_NLS 2299setlocale(LC_ALL, ""); 2300bindtextdomain(PACKAGE, LOCALEDIR); 2301textdomain(PACKAGE); 2302#endif /* ENABLE_NLS */ 2303} 2304 2305void 2306_version () 2307{ 2308 version_etc (stdout, PROGRAM_NAME, PACKAGE_NAME, VERSION, AUTHORS, 2309 (char *) NULL); 2310} 2311 2312static int 2313_parse_options (int* argc_ptr, char*** argv_ptr) 2314{ 2315int opt, help = 0, list = 0, version = 0, wrong = 0; 2316 2317while (1) 2318{ 2319 opt = getopt_long (*argc_ptr, *argv_ptr, "hilmsv", 2320 options, NULL); 2321 if (opt == -1) 2322 break; 2323 2324 switch (opt) { 2325 case 'h': help = 1; break; 2326 case 'l': list = 1; break; 2327 case 'm': opt_machine_mode = 1; break; 2328 case 's': opt_script_mode = 1; break; 2329 case 'v': version = 1; break; 2330 case PRETEND_INPUT_TTY: 2331 pretend_input_tty = 1; 2332 break; 2333 default: wrong = 1; break; 2334 } 2335} 2336 2337if (wrong == 1) { 2338 fprintf (stderr, 2339 _("Usage: %s [-hlmsv] [DEVICE [COMMAND [PARAMETERS]]...]\n"), 2340 program_name); 2341 return 0; 2342} 2343 2344if (version == 1) { 2345 _version (); 2346 exit (EXIT_SUCCESS); 2347} 2348 2349if (help == 1) { 2350 help_msg (); 2351 exit (EXIT_SUCCESS); 2352} 2353 2354if (list == 1) { 2355 _print_list (); 2356 exit (EXIT_SUCCESS); 2357} 2358 2359*argc_ptr -= optind; 2360*argv_ptr += optind; 2361return 1; 2362} 2363 2364static PedDevice* 2365_choose_device (int* argc_ptr, char*** argv_ptr) 2366{ 2367PedDevice* dev; 2368 2369/* specified on comand line? */ 2370if (*argc_ptr) { 2371 dev = ped_device_get ((*argv_ptr) [0]); 2372 if (!dev) 2373 return NULL; 2374 (*argc_ptr)--; 2375 (*argv_ptr)++; 2376} else { 2377retry: 2378 ped_device_probe_all (); 2379 dev = ped_device_get_next (NULL); 2380 if (!dev) { 2381 if (ped_exception_throw (PED_EXCEPTION_ERROR, 2382 PED_EXCEPTION_RETRY_CANCEL, 2383 _("No device found")) 2384 == PED_EXCEPTION_RETRY) 2385 goto retry; 2386 else 2387 return NULL; 2388 } 2389} 2390 2391if (!ped_device_open (dev)) 2392 return NULL; 2393return dev; 2394} 2395 2396static PedDevice* 2397_init (int* argc_ptr, char*** argv_ptr) 2398{ 2399PedDevice* dev; 2400 2401#ifdef ENABLE_MTRACE 2402mtrace(); 2403#endif 2404 2405_init_i18n (); 2406if (!init_ui ()) 2407 goto error; 2408_init_messages (); 2409_init_commands (); 2410 2411if (!_parse_options (argc_ptr, argv_ptr)) 2412 goto error_done_commands; 2413 2414#ifdef HAVE_GETUID 2415 if (getuid() != 0 && !opt_script_mode) { 2416 puts (_("WARNING: You are not superuser. Watch out for " 2417 "permissions.")); 2418 } 2419#endif 2420 2421dev = _choose_device (argc_ptr, argv_ptr); 2422if (!dev) 2423 goto error_done_commands; 2424 2425g_timer = ped_timer_new (_timer_handler, &timer_context); 2426if (!g_timer) 2427 goto error_done_commands; 2428timer_context.last_update = 0; 2429 2430return dev; 2431 2432error_done_commands: 2433_done_commands (); 2434_done_messages (); 2435done_ui (); 2436error: 2437return NULL; 2438} 2439 2440static void 2441_done (PedDevice* dev) 2442{ 2443if (dev->boot_dirty && dev->type != PED_DEVICE_FILE) { 2444 ped_exception_throw ( 2445 PED_EXCEPTION_WARNING, 2446 PED_EXCEPTION_OK, 2447 _("You should reinstall your boot loader before " 2448 "rebooting. Read section 4 of the Parted User " 2449 "documentation for more information.")); 2450} 2451 2452#if !defined(__sun) 2453if (!opt_script_mode && !opt_machine_mode && disk_is_modified) { 2454 ped_exception_throw ( 2455 PED_EXCEPTION_INFORMATION, PED_EXCEPTION_OK, 2456 _("You may need to update /etc/fstab.\n")); 2457} 2458#endif 2459 2460ped_device_close (dev); 2461 2462ped_timer_destroy (g_timer); 2463_done_commands (); 2464_done_messages (); 2465done_ui(); 2466} 2467 2468int 2469main (int argc, char** argv) 2470{ 2471 PedDevice* dev; 2472 int status; 2473 2474 program_name = argv[0]; 2475 atexit (close_stdout); 2476 2477 dev = _init (&argc, &argv); 2478 if (!dev) 2479 return 1; 2480 2481 if (argc || opt_script_mode) 2482 status = non_interactive_mode (&dev, commands, argc, argv); 2483 else 2484 status = interactive_mode (&dev, commands); 2485 2486 _done (dev); 2487 2488 return !status; 2489} 2490