2006-12-06 17:25:32 -06:00
/* fdisk.c -- Partition table manipulator for Linux.
*
* Copyright ( C ) 1992 A . V . Le Blanc ( LeBlanc @ mcc . ac . uk )
2012-06-17 11:10:07 -05:00
* Copyright ( C ) 2012 Davidlohr Bueso < dave @ gnu . org >
2006-12-06 17:25:32 -06:00
*
* This program is free software . You can redistribute it and / or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation : either version 1 or
* ( at your option ) any later version .
*/
# include <unistd.h>
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
# include <fcntl.h>
# include <ctype.h>
# include <errno.h>
2006-12-06 17:25:35 -06:00
# include <getopt.h>
# include <sys/stat.h>
2008-01-16 12:53:56 -06:00
# include <sys/time.h>
2007-07-06 20:32:31 -05:00
# include <time.h>
2008-08-19 06:53:28 -05:00
# include <limits.h>
2006-12-06 17:25:32 -06:00
2011-01-23 15:51:21 -06:00
# include "xalloc.h"
2006-12-06 17:25:43 -06:00
# include "nls.h"
2011-01-02 15:58:13 -06:00
# include "rpmatch.h"
2007-11-07 12:05:31 -06:00
# include "blkdev.h"
2006-12-06 17:25:39 -06:00
# include "common.h"
2010-03-09 02:21:35 -06:00
# include "mbsalign.h"
2006-12-06 17:25:33 -06:00
# include "fdisk.h"
2009-03-11 08:00:21 -05:00
# include "wholedisk.h"
2010-12-16 18:28:59 -06:00
# include "pathnames.h"
# include "canonicalize.h"
2011-08-17 06:21:12 -05:00
# include "strutils.h"
2012-04-04 13:02:04 -05:00
# include "closestream.h"
2006-12-06 17:25:37 -06:00
2006-12-06 17:25:35 -06:00
# include "fdisksunlabel.h"
2006-12-06 17:25:37 -06:00
# include "fdisksgilabel.h"
2007-06-27 16:49:56 -05:00
# include "fdiskmaclabel.h"
2012-04-28 17:02:45 -05:00
# include "fdiskdoslabel.h"
2012-05-20 11:11:33 -05:00
# include "fdiskbsdlabel.h"
2006-12-06 17:25:37 -06:00
2006-12-06 17:26:54 -06:00
# ifdef HAVE_LINUX_COMPILER_H
# include <linux/compiler.h>
# endif
# ifdef HAVE_LINUX_BLKPG_H
2006-12-06 17:25:39 -06:00
# include <linux/blkpg.h>
# endif
2006-12-06 17:25:32 -06:00
2011-11-09 12:04:12 -06:00
/* menu list description */
struct menulist_descr {
char command ; /* command key */
char * description ; /* command description */
2012-07-22 12:05:01 -05:00
enum fdisk_labeltype label [ 2 ] ; /* disklabel types associated with main and expert menu */
2011-11-09 12:04:12 -06:00
} ;
static const struct menulist_descr menulist [ ] = {
2013-02-11 03:36:17 -06:00
{ ' a ' , N_ ( " change number of alternate cylinders " ) , { 0 , FDISK_DISKLABEL_SUN } } ,
{ ' a ' , N_ ( " select bootable partition " ) , { FDISK_DISKLABEL_SGI , 0 } } ,
2012-11-25 22:25:49 -06:00
{ ' a ' , N_ ( " toggle a bootable flag " ) , { FDISK_DISKLABEL_DOS , 0 } } ,
{ ' a ' , N_ ( " toggle a read only flag " ) , { FDISK_DISKLABEL_SUN , 0 } } ,
{ ' b ' , N_ ( " edit bootfile entry " ) , { FDISK_DISKLABEL_SGI , 0 } } ,
2013-02-11 03:36:17 -06:00
{ ' b ' , N_ ( " edit bsd disklabel " ) , { FDISK_DISKLABEL_DOS , 0 } } ,
2012-11-25 22:25:49 -06:00
{ ' b ' , N_ ( " move beginning of data in a partition " ) , { 0 , FDISK_DISKLABEL_DOS } } ,
2013-02-11 03:36:17 -06:00
{ ' c ' , N_ ( " change number of cylinders " ) , { 0 , FDISK_DISKLABEL_DOS | FDISK_DISKLABEL_SUN } } ,
{ ' c ' , N_ ( " select sgi swap partition " ) , { FDISK_DISKLABEL_SGI , 0 } } ,
2012-11-25 22:25:49 -06:00
{ ' c ' , N_ ( " toggle the dos compatibility flag " ) , { FDISK_DISKLABEL_DOS , 0 } } ,
{ ' c ' , N_ ( " toggle the mountable flag " ) , { FDISK_DISKLABEL_SUN , 0 } } ,
{ ' d ' , N_ ( " delete a partition " ) , { FDISK_DISKLABEL_DOS | FDISK_DISKLABEL_SUN | FDISK_DISKLABEL_SGI | FDISK_DISKLABEL_OSF | FDISK_DISKLABEL_GPT , 0 } } ,
{ ' d ' , N_ ( " print the raw data in the partition table " ) , { 0 , FDISK_DISKLABEL_ANY } } ,
{ ' e ' , N_ ( " change number of extra sectors per cylinder " ) , { 0 , FDISK_DISKLABEL_SUN } } ,
{ ' e ' , N_ ( " edit drive data " ) , { FDISK_DISKLABEL_OSF , 0 } } ,
2013-02-11 03:36:17 -06:00
{ ' e ' , N_ ( " list extended partitions " ) , { 0 , FDISK_DISKLABEL_DOS } } ,
2012-11-25 22:25:49 -06:00
{ ' f ' , N_ ( " fix partition order " ) , { 0 , FDISK_DISKLABEL_DOS } } ,
{ ' g ' , N_ ( " create a new empty GPT partition table " ) , { ~ FDISK_DISKLABEL_OSF , 0 } } ,
2013-02-11 03:36:17 -06:00
{ ' g ' , N_ ( " create an IRIX (SGI) partition table " ) , { 0 , FDISK_DISKLABEL_ANY } } , /* for backward compatibility only */
{ ' G ' , N_ ( " create an IRIX (SGI) partition table " ) , { ~ FDISK_DISKLABEL_OSF , 0 } } ,
2012-11-25 22:25:49 -06:00
{ ' h ' , N_ ( " change number of heads " ) , { 0 , FDISK_DISKLABEL_DOS | FDISK_DISKLABEL_SUN } } ,
{ ' i ' , N_ ( " change interleave factor " ) , { 0 , FDISK_DISKLABEL_SUN } } ,
{ ' i ' , N_ ( " change the disk identifier " ) , { 0 , FDISK_DISKLABEL_DOS } } ,
{ ' i ' , N_ ( " install bootstrap " ) , { FDISK_DISKLABEL_OSF , 0 } } ,
{ ' l ' , N_ ( " list known partition types " ) , { FDISK_DISKLABEL_DOS | FDISK_DISKLABEL_SUN | FDISK_DISKLABEL_SGI | FDISK_DISKLABEL_OSF | FDISK_DISKLABEL_GPT , 0 } } ,
{ ' m ' , N_ ( " print this menu " ) , { FDISK_DISKLABEL_ANY , FDISK_DISKLABEL_ANY } } ,
{ ' n ' , N_ ( " add a new partition " ) , { FDISK_DISKLABEL_DOS | FDISK_DISKLABEL_SUN | FDISK_DISKLABEL_SGI | FDISK_DISKLABEL_OSF | FDISK_DISKLABEL_GPT , 0 } } ,
{ ' o ' , N_ ( " change rotation speed (rpm) " ) , { 0 , FDISK_DISKLABEL_SUN } } ,
2013-02-11 03:36:17 -06:00
{ ' o ' , N_ ( " create a new empty DOS partition table " ) , { ~ FDISK_DISKLABEL_OSF , 0 } } ,
2012-11-25 22:25:49 -06:00
{ ' p ' , N_ ( " print the partition table " ) , { FDISK_DISKLABEL_DOS | FDISK_DISKLABEL_SUN | FDISK_DISKLABEL_SGI | FDISK_DISKLABEL_OSF , FDISK_DISKLABEL_DOS | FDISK_DISKLABEL_SUN } } ,
{ ' q ' , N_ ( " quit without saving changes " ) , { FDISK_DISKLABEL_ANY , FDISK_DISKLABEL_ANY } } ,
{ ' r ' , N_ ( " return to main menu " ) , { FDISK_DISKLABEL_OSF , FDISK_DISKLABEL_DOS | FDISK_DISKLABEL_SUN | FDISK_DISKLABEL_SGI | FDISK_DISKLABEL_OSF } } ,
{ ' s ' , N_ ( " change number of sectors/track " ) , { 0 , FDISK_DISKLABEL_DOS | FDISK_DISKLABEL_SUN } } ,
2013-02-11 03:36:17 -06:00
{ ' s ' , N_ ( " create a new empty Sun disklabel " ) , { ~ FDISK_DISKLABEL_OSF , 0 } } ,
2012-11-25 22:25:49 -06:00
{ ' s ' , N_ ( " show complete disklabel " ) , { FDISK_DISKLABEL_OSF , 0 } } ,
{ ' t ' , N_ ( " change a partition's system id " ) , { FDISK_DISKLABEL_DOS | FDISK_DISKLABEL_SUN | FDISK_DISKLABEL_SGI | FDISK_DISKLABEL_OSF , 0 } } ,
{ ' u ' , N_ ( " change display/entry units " ) , { FDISK_DISKLABEL_DOS | FDISK_DISKLABEL_SUN | FDISK_DISKLABEL_SGI | FDISK_DISKLABEL_OSF , 0 } } ,
{ ' v ' , N_ ( " verify the partition table " ) , { FDISK_DISKLABEL_DOS | FDISK_DISKLABEL_SUN | FDISK_DISKLABEL_SGI , FDISK_DISKLABEL_DOS | FDISK_DISKLABEL_SUN | FDISK_DISKLABEL_SGI } } ,
{ ' w ' , N_ ( " write disklabel to disk " ) , { FDISK_DISKLABEL_OSF , 0 } } ,
2013-02-11 03:36:17 -06:00
{ ' w ' , N_ ( " write table to disk and exit " ) , { FDISK_DISKLABEL_DOS | FDISK_DISKLABEL_SUN | FDISK_DISKLABEL_SGI | FDISK_DISKLABEL_GPT , FDISK_DISKLABEL_DOS | FDISK_DISKLABEL_SUN | FDISK_DISKLABEL_SGI } } ,
2012-11-25 22:25:49 -06:00
{ ' x ' , N_ ( " extra functionality (experts only) " ) , { FDISK_DISKLABEL_DOS | FDISK_DISKLABEL_SUN | FDISK_DISKLABEL_SGI , 0 } } ,
2011-11-09 12:04:12 -06:00
# if !defined (__alpha__)
2012-11-25 22:25:49 -06:00
{ ' x ' , N_ ( " link BSD partition to non-BSD partition " ) , { FDISK_DISKLABEL_OSF , 0 } } ,
2011-11-09 12:04:12 -06:00
# endif
2012-11-25 22:25:49 -06:00
{ ' y ' , N_ ( " change number of physical cylinders " ) , { 0 , FDISK_DISKLABEL_SUN } } ,
2011-11-09 12:04:12 -06:00
} ;
2012-09-24 04:30:26 -05:00
2012-05-27 14:44:13 -05:00
sector_t get_nr_sects ( struct partition * p ) {
2006-12-06 17:25:35 -06:00
return read4_little_endian ( p - > size4 ) ;
}
2012-05-21 15:28:03 -05:00
char * line_ptr , /* interactive input */
2006-12-06 17:25:43 -06:00
line_buffer [ LINE_LENGTH ] ;
2006-12-06 17:25:32 -06:00
2013-01-22 06:46:55 -06:00
int nowarn = 0 ; /* no warnings for fdisk -l/-s */
2006-12-06 17:25:32 -06:00
2006-12-06 17:26:12 -06:00
unsigned int user_cylinders , user_heads , user_sectors ;
2011-07-03 05:01:21 -05:00
2013-02-11 09:38:20 -06:00
void toggle_units ( struct fdisk_context * cxt )
{
fdisk_context_set_unit ( cxt ,
fdisk_context_use_cylinders ( cxt ) ? " sectors " :
" cylinders " ) ;
if ( fdisk_context_use_cylinders ( cxt ) )
fdisk_info ( cxt , _ ( " Changing display/entry units to cylinders (DEPRECATED!). " ) ) ;
else
fdisk_info ( cxt , _ ( " Changing display/entry units to sectors. " ) ) ;
}
2011-01-23 15:51:20 -06:00
static void __attribute__ ( ( __noreturn__ ) ) usage ( FILE * out )
{
fprintf ( out , _ ( " Usage: \n "
" %1$s [options] <disk> change partition table \n "
" %1$s [options] -l <disk> list partition table(s) \n "
" %1$s -s <partition> give partition size(s) in blocks \n "
" \n Options: \n "
" -b <size> sector size (512, 1024, 2048 or 4096) \n "
" -c[=<mode>] compatible mode: 'dos' or 'nondos' (default) \n "
" -h print this help text \n "
" -u[=<unit>] display units: 'cylinders' or 'sectors' (default) \n "
" -v print program version \n "
" -C <number> specify the number of cylinders \n "
" -H <number> specify the number of heads \n "
" -S <number> specify the number of sectors per track \n "
" \n " ) , program_invocation_short_name ) ;
exit ( out = = stderr ? EXIT_FAILURE : EXIT_SUCCESS ) ;
}
2012-07-25 14:15:35 -05:00
void __attribute__ ( ( __noreturn__ ) )
fatal ( struct fdisk_context * cxt , enum failure why )
2012-04-27 06:23:42 -05:00
{
2012-05-21 15:28:03 -05:00
close ( cxt - > dev_fd ) ;
2006-12-06 17:25:32 -06:00
switch ( why ) {
case unable_to_read :
2012-05-21 15:28:03 -05:00
err ( EXIT_FAILURE , _ ( " unable to read %s " ) , cxt - > dev_path ) ;
2011-01-23 15:58:14 -06:00
2006-12-06 17:25:32 -06:00
case unable_to_seek :
2012-05-21 15:28:03 -05:00
err ( EXIT_FAILURE , _ ( " unable to seek on %s " ) , cxt - > dev_path ) ;
2011-01-23 15:58:14 -06:00
2006-12-06 17:25:32 -06:00
case unable_to_write :
2012-05-21 15:28:03 -05:00
err ( EXIT_FAILURE , _ ( " unable to write %s " ) , cxt - > dev_path ) ;
2011-01-23 15:58:14 -06:00
2006-12-06 17:25:39 -06:00
case ioctl_error :
2012-05-21 15:28:03 -05:00
err ( EXIT_FAILURE , _ ( " BLKGETSIZE ioctl failed on %s " ) , cxt - > dev_path ) ;
2011-01-23 15:58:14 -06:00
2006-12-06 17:25:46 -06:00
default :
2011-01-23 15:58:14 -06:00
err ( EXIT_FAILURE , _ ( " fatal error " ) ) ;
2006-12-06 17:25:32 -06:00
}
}
2006-12-06 17:25:43 -06:00
struct partition *
get_part_table ( int i ) {
return ptes [ i ] . part_table ;
}
2012-11-25 22:25:49 -06:00
void print_menu ( struct fdisk_context * cxt , enum menutype menu )
2011-11-09 12:04:12 -06:00
{
size_t i ;
2012-12-11 11:30:03 -06:00
int id ;
2006-12-06 17:25:32 -06:00
2011-11-09 12:04:12 -06:00
puts ( _ ( " Command action " ) ) ;
2012-12-11 11:30:03 -06:00
id = cxt & & cxt - > label ? cxt - > label - > id : FDISK_DISKLABEL_ANY ;
2011-11-09 12:04:12 -06:00
for ( i = 0 ; i < ARRAY_SIZE ( menulist ) ; i + + )
2012-12-11 11:30:03 -06:00
if ( menulist [ i ] . label [ menu ] & id )
2011-11-09 12:04:12 -06:00
printf ( " %c %s \n " , menulist [ i ] . command , menulist [ i ] . description ) ;
2006-12-06 17:25:32 -06:00
}
2012-09-24 06:24:09 -05:00
void list_partition_types ( struct fdisk_context * cxt )
2006-12-06 17:25:32 -06:00
{
2012-09-24 06:24:09 -05:00
struct fdisk_parttype * types ;
2013-04-18 07:38:49 -05:00
size_t ntypes = 0 ;
2006-12-06 17:25:32 -06:00
2012-09-24 06:24:09 -05:00
if ( ! cxt | | ! cxt - > label | | ! cxt - > label - > parttypes )
return ;
2006-12-06 17:25:35 -06:00
2012-09-24 06:24:09 -05:00
types = cxt - > label - > parttypes ;
2013-04-18 07:38:49 -05:00
ntypes = cxt - > label - > nparttypes ;
2006-12-06 17:25:32 -06:00
2012-09-24 06:24:09 -05:00
if ( types [ 0 ] . typestr = = NULL ) {
/*
* Prints in 4 columns in format < hex > < name >
*/
2013-04-18 07:38:49 -05:00
size_t last [ 4 ] , done = 0 , next = 0 , size ;
int i ;
2010-03-09 02:21:35 -06:00
2013-04-18 07:38:49 -05:00
size = ntypes ;
if ( types [ ntypes - 1 ] . name = = NULL )
size - - ;
2012-09-24 06:24:09 -05:00
for ( i = 3 ; i > = 0 ; i - - )
last [ 3 - i ] = done + = ( size + i - done ) / ( i + 1 ) ;
i = done = 0 ;
do {
# define NAME_WIDTH 15
char name [ NAME_WIDTH * MB_LEN_MAX ] ;
size_t width = NAME_WIDTH ;
struct fdisk_parttype * t = & types [ next ] ;
size_t ret ;
2013-04-18 07:38:49 -05:00
if ( t - > name ) {
printf ( " %c%2x " , i ? ' ' : ' \n ' , t - > type ) ;
ret = mbsalign ( _ ( t - > name ) , name , sizeof ( name ) ,
& width , MBS_ALIGN_LEFT , 0 ) ;
2012-09-24 06:24:09 -05:00
2013-04-18 07:38:49 -05:00
if ( ret = = ( size_t ) - 1 | | ret > = sizeof ( name ) )
printf ( " %-15.15s " , _ ( t - > name ) ) ;
else
fputs ( name , stdout ) ;
}
2012-09-24 06:24:09 -05:00
next = last [ i + + ] + done ;
if ( i > 3 | | next > = last [ i ] ) {
i = 0 ;
next = + + done ;
}
} while ( done < last [ 0 ] ) ;
} else {
/*
* Prints 1 column in format < idx > < name > < typestr >
*/
struct fdisk_parttype * t ;
2013-04-18 07:38:49 -05:00
size_t i ;
2012-09-24 06:24:09 -05:00
2013-04-18 07:38:49 -05:00
for ( i = 0 , t = types ; t & & i < ntypes ; t + + , i + + ) {
if ( t - > name )
printf ( " %3zu %-30s %s \n " , i + 1 ,
t - > name , t - > typestr ) ;
}
2012-09-24 06:24:09 -05:00
}
2006-12-06 17:25:32 -06:00
putchar ( ' \n ' ) ;
}
2006-12-06 17:25:43 -06:00
static int
test_c ( char * * m , char * mesg ) {
2006-12-06 17:25:32 -06:00
int val = 0 ;
if ( ! * m )
2006-12-06 17:25:39 -06:00
fprintf ( stderr , _ ( " You must set " ) ) ;
2006-12-06 17:25:32 -06:00
else {
fprintf ( stderr , " %s " , * m ) ;
val = 1 ;
}
* m = mesg ;
return val ;
}
2012-06-17 11:10:33 -05:00
int warn_geometry ( struct fdisk_context * cxt )
2012-04-28 17:02:45 -05:00
{
2006-12-06 17:25:32 -06:00
char * m = NULL ;
int prev = 0 ;
2006-12-06 17:26:30 -06:00
2012-11-25 22:25:49 -06:00
if ( fdisk_is_disklabel ( cxt , SGI ) ) /* cannot set cylinders etc anyway */
2006-12-06 17:26:30 -06:00
return 0 ;
2012-06-17 11:10:33 -05:00
if ( ! cxt - > geom . heads )
2006-12-06 17:25:39 -06:00
prev = test_c ( & m , _ ( " heads " ) ) ;
2012-06-17 11:10:33 -05:00
if ( ! cxt - > geom . sectors )
2006-12-06 17:25:39 -06:00
prev = test_c ( & m , _ ( " sectors " ) ) ;
2012-06-17 11:10:33 -05:00
if ( ! cxt - > geom . cylinders )
2006-12-06 17:25:39 -06:00
prev = test_c ( & m , _ ( " cylinders " ) ) ;
2006-12-06 17:25:32 -06:00
if ( ! m )
return 0 ;
fprintf ( stderr ,
2006-12-06 17:25:39 -06:00
_ ( " %s%s. \n You can do this from the extra functions menu. \n " ) ,
prev ? _ ( " and " ) : " " , m ) ;
2006-12-06 17:25:32 -06:00
return 1 ;
}
2012-06-03 13:15:17 -05:00
void warn_limits ( struct fdisk_context * cxt )
2012-04-28 17:02:45 -05:00
{
2012-06-03 13:15:20 -05:00
if ( cxt - > total_sectors > UINT_MAX & & ! nowarn ) {
unsigned long long bytes = cxt - > total_sectors * cxt - > sector_size ;
2010-08-23 05:11:26 -05:00
int giga = bytes / 1000000000 ;
2008-08-20 16:27:50 -05:00
int hectogiga = ( giga + 50 ) / 100 ;
2008-08-19 06:53:28 -05:00
fprintf ( stderr , _ ( " \n "
" WARNING: The size of this disk is %d.%d TB (%llu bytes). \n "
2008-08-20 16:27:50 -05:00
" DOS partition table format can not be used on drives for volumes \n "
2012-06-03 13:15:17 -05:00
" larger than (%llu bytes) for %ld-byte sectors. Use parted(1) and GUID \n "
2008-08-19 06:53:28 -05:00
" partition table format (GPT). \n \n " ) ,
2008-08-20 16:27:50 -05:00
hectogiga / 10 , hectogiga % 10 ,
2010-08-23 05:11:26 -05:00
bytes ,
2012-06-03 13:15:17 -05:00
( sector_t ) UINT_MAX * cxt - > sector_size ,
cxt - > sector_size ) ;
2008-08-19 06:53:28 -05:00
}
2006-12-06 17:25:32 -06:00
}
2013-01-18 09:11:40 -06:00
static void maybe_exit ( struct fdisk_context * cxt , int rc , int * asked )
2011-01-02 15:58:12 -06:00
{
char line [ LINE_LENGTH ] ;
2013-01-18 09:11:40 -06:00
assert ( cxt ) ;
assert ( cxt - > label ) ;
2011-01-02 15:58:12 -06:00
putchar ( ' \n ' ) ;
2011-01-05 09:50:47 -06:00
if ( asked )
* asked = 0 ;
2011-01-02 15:58:12 -06:00
2013-01-18 09:11:40 -06:00
if ( fdisk_label_is_changed ( cxt - > label ) ) {
2011-01-02 15:58:12 -06:00
fprintf ( stderr , _ ( " Do you really want to quit? " ) ) ;
if ( ! fgets ( line , LINE_LENGTH , stdin ) | | rpmatch ( line ) = = 1 )
2013-01-18 09:11:40 -06:00
goto leave ;
2011-01-05 09:50:47 -06:00
if ( asked )
* asked = 1 ;
2013-01-18 09:11:40 -06:00
return ;
}
leave :
fdisk_free_context ( cxt ) ;
exit ( rc ) ;
2011-01-02 15:58:12 -06:00
}
2006-12-06 17:25:37 -06:00
/* read line; return 0 or first char */
2013-01-18 09:11:40 -06:00
int read_line ( struct fdisk_context * cxt , int * asked )
2006-12-06 17:25:32 -06:00
{
2006-12-06 17:25:37 -06:00
line_ptr = line_buffer ;
2006-12-06 17:25:39 -06:00
if ( ! fgets ( line_buffer , LINE_LENGTH , stdin ) ) {
2013-01-18 09:11:40 -06:00
maybe_exit ( cxt , 1 , asked ) ;
2006-12-06 17:25:32 -06:00
return 0 ;
2006-12-06 17:25:39 -06:00
}
2011-01-05 09:50:47 -06:00
if ( asked )
* asked = 0 ;
2006-12-06 17:25:32 -06:00
while ( * line_ptr & & ! isgraph ( * line_ptr ) )
line_ptr + + ;
return * line_ptr ;
}
2013-01-18 09:11:40 -06:00
char read_char ( struct fdisk_context * cxt , char * mesg )
2006-12-06 17:25:32 -06:00
{
2006-12-06 17:25:35 -06:00
do {
2006-12-06 17:25:32 -06:00
fputs ( mesg , stdout ) ;
2006-12-06 17:25:44 -06:00
fflush ( stdout ) ; /* requested by niles@scyld.com */
2013-01-18 09:11:40 -06:00
} while ( ! read_line ( cxt , NULL ) ) ;
2006-12-06 17:25:32 -06:00
return * line_ptr ;
}
2013-01-18 09:11:40 -06:00
char read_chars ( struct fdisk_context * cxt , char * mesg )
2006-12-06 17:25:35 -06:00
{
2011-01-05 09:50:47 -06:00
int rc , asked = 0 ;
do {
fputs ( mesg , stdout ) ;
fflush ( stdout ) ; /* niles@scyld.com */
2013-01-18 09:11:40 -06:00
rc = read_line ( cxt , & asked ) ;
2011-01-05 09:50:47 -06:00
} while ( asked ) ;
if ( ! rc ) {
2006-12-06 17:25:35 -06:00
* line_ptr = ' \n ' ;
2006-12-06 17:25:37 -06:00
line_ptr [ 1 ] = 0 ;
}
return * line_ptr ;
2006-12-06 17:25:35 -06:00
}
2012-09-25 03:23:36 -05:00
struct fdisk_parttype * read_partition_type ( struct fdisk_context * cxt )
2006-12-06 17:25:32 -06:00
{
2012-09-25 03:23:36 -05:00
if ( ! cxt | | ! cxt - > label | | ! cxt - > label - > nparttypes )
return NULL ;
do {
size_t sz ;
if ( cxt - > label - > parttypes [ 0 ] . typestr )
2013-01-18 09:11:40 -06:00
read_chars ( cxt , _ ( " Partition type (type L to list all types): " ) ) ;
2012-09-25 03:23:36 -05:00
else
2013-01-18 09:11:40 -06:00
read_chars ( cxt , _ ( " Hex code (type L to list all codes): " ) ) ;
2012-09-25 03:23:36 -05:00
sz = strlen ( line_ptr ) ;
if ( ! sz | | line_ptr [ sz - 1 ] ! = ' \n ' | | sz = = 1 )
continue ;
line_ptr [ sz - 1 ] = ' \0 ' ;
if ( tolower ( * line_ptr ) = = ' l ' )
list_partition_types ( cxt ) ;
else
return fdisk_parse_parttype ( cxt , line_ptr ) ;
} while ( 1 ) ;
return NULL ;
2006-12-06 17:25:33 -06:00
}
2012-09-25 03:23:36 -05:00
2012-05-06 07:10:18 -05:00
unsigned int
2012-06-03 13:15:17 -05:00
read_int_with_suffix ( struct fdisk_context * cxt ,
unsigned int low , unsigned int dflt , unsigned int high ,
2012-01-15 23:36:12 -06:00
unsigned int base , char * mesg , int * is_suffix_used )
2006-12-06 17:25:33 -06:00
{
2012-01-15 23:36:12 -06:00
unsigned int res ;
2006-12-06 17:25:37 -06:00
int default_ok = 1 ;
2012-01-15 23:36:13 -06:00
int absolute = 0 ;
2006-12-06 17:25:37 -06:00
static char * ms = NULL ;
2011-08-01 08:19:53 -05:00
static size_t mslen = 0 ;
2006-12-06 17:25:37 -06:00
2006-12-06 17:25:46 -06:00
if ( ! ms | | strlen ( mesg ) + 100 > mslen ) {
mslen = strlen ( mesg ) + 200 ;
2011-01-23 15:51:21 -06:00
ms = xrealloc ( ms , mslen ) ;
2006-12-06 17:25:33 -06:00
}
2006-12-06 17:25:32 -06:00
2006-12-06 17:25:37 -06:00
if ( dflt < low | | dflt > high )
default_ok = 0 ;
if ( default_ok )
2006-12-06 17:26:12 -06:00
snprintf ( ms , mslen , _ ( " %s (%u-%u, default %u): " ) ,
2006-12-06 17:25:46 -06:00
mesg , low , high , dflt ) ;
2006-12-06 17:25:37 -06:00
else
2006-12-06 17:26:12 -06:00
snprintf ( ms , mslen , " %s (%u-%u): " ,
2006-12-06 17:25:46 -06:00
mesg , low , high ) ;
2006-12-06 17:25:37 -06:00
2006-12-06 17:25:32 -06:00
while ( 1 ) {
2006-12-06 17:25:37 -06:00
int use_default = default_ok ;
/* ask question and read answer */
2013-01-18 09:11:40 -06:00
while ( read_chars ( cxt , ms ) ! = ' \n ' & & ! isdigit ( * line_ptr )
2006-12-06 17:25:37 -06:00
& & * line_ptr ! = ' - ' & & * line_ptr ! = ' + ' )
continue ;
2006-12-06 17:25:33 -06:00
if ( * line_ptr = = ' + ' | | * line_ptr = = ' - ' ) {
2006-12-06 17:26:08 -06:00
int minus = ( * line_ptr = = ' - ' ) ;
2007-12-12 18:06:44 -06:00
int suflen ;
2006-12-06 17:26:08 -06:00
2012-01-15 23:36:13 -06:00
absolute = 0 ;
2012-01-15 23:36:12 -06:00
res = atoi ( line_ptr + 1 ) ;
2006-12-06 17:26:08 -06:00
2007-12-12 18:06:44 -06:00
while ( isdigit ( * + + line_ptr ) )
2006-12-06 17:25:33 -06:00
use_default = 0 ;
2006-12-06 17:26:08 -06:00
2011-05-09 09:00:36 -05:00
while ( isspace ( * line_ptr ) )
line_ptr + + ;
2007-12-12 18:06:44 -06:00
suflen = strlen ( line_ptr ) - 1 ;
while ( isspace ( * ( line_ptr + suflen ) ) )
* ( line_ptr + suflen - - ) = ' \0 ' ;
if ( ( * line_ptr = = ' C ' | | * line_ptr = = ' c ' ) & &
* ( line_ptr + 1 ) = = ' \0 ' ) {
/*
* Cylinders
*/
2013-02-11 09:38:20 -06:00
if ( fdisk_context_use_cylinders ( cxt ) )
2012-06-17 11:10:33 -05:00
res * = cxt - > geom . heads * cxt - > geom . sectors ;
2008-11-13 16:08:34 -06:00
} else if ( * line_ptr & &
* ( line_ptr + 1 ) = = ' B ' & &
2007-12-12 18:06:44 -06:00
* ( line_ptr + 2 ) = = ' \0 ' ) {
/*
* 10 ^ N
*/
if ( * line_ptr = = ' K ' )
2006-12-06 17:26:08 -06:00
absolute = 1000 ;
2007-12-12 18:06:44 -06:00
else if ( * line_ptr = = ' M ' )
2006-12-06 17:26:08 -06:00
absolute = 1000000 ;
2007-12-12 18:06:44 -06:00
else if ( * line_ptr = = ' G ' )
2006-12-06 17:26:08 -06:00
absolute = 1000000000 ;
2007-12-12 18:06:44 -06:00
else
absolute = - 1 ;
2008-11-13 16:08:34 -06:00
} else if ( * line_ptr & &
* ( line_ptr + 1 ) = = ' \0 ' ) {
2007-12-12 18:06:44 -06:00
/*
* 2 ^ N
*/
if ( * line_ptr = = ' K ' )
absolute = 1 < < 10 ;
else if ( * line_ptr = = ' M ' )
absolute = 1 < < 20 ;
else if ( * line_ptr = = ' G ' )
absolute = 1 < < 30 ;
else
absolute = - 1 ;
} else if ( * line_ptr ! = ' \0 ' )
absolute = - 1 ;
if ( absolute = = - 1 ) {
printf ( _ ( " Unsupported suffix: '%s'. \n " ) , line_ptr ) ;
printf ( _ ( " Supported: 10^N: KB (KiloByte), MB (MegaByte), GB (GigaByte) \n "
" 2^N: K (KibiByte), M (MebiByte), G (GibiByte) \n " ) ) ;
continue ;
2006-12-06 17:25:33 -06:00
}
2007-12-12 18:06:44 -06:00
2012-01-15 23:36:12 -06:00
if ( absolute & & res ) {
2006-12-06 17:26:08 -06:00
unsigned long long bytes ;
unsigned long unit ;
2012-01-15 23:36:12 -06:00
bytes = ( unsigned long long ) res * absolute ;
2013-02-11 09:38:20 -06:00
unit = cxt - > sector_size * fdisk_context_get_units_per_sector ( cxt ) ;
2006-12-06 17:26:08 -06:00
bytes + = unit / 2 ; /* round */
bytes / = unit ;
2012-01-15 23:36:12 -06:00
res = bytes ;
2006-12-06 17:26:08 -06:00
}
if ( minus )
2012-01-15 23:36:12 -06:00
res = - res ;
res + = base ;
2006-12-06 17:25:37 -06:00
} else {
2012-01-15 23:36:12 -06:00
res = atoi ( line_ptr ) ;
2006-12-06 17:25:37 -06:00
while ( isdigit ( * line_ptr ) ) {
2006-12-06 17:25:33 -06:00
line_ptr + + ;
use_default = 0 ;
}
}
2012-01-15 23:36:13 -06:00
if ( use_default ) {
printf ( _ ( " Using default value %u \n " ) , dflt ) ;
return dflt ;
}
2012-01-15 23:36:12 -06:00
if ( res > = low & & res < = high )
2006-12-06 17:25:32 -06:00
break ;
2006-12-06 17:25:33 -06:00
else
2006-12-06 17:25:39 -06:00
printf ( _ ( " Value out of range. \n " ) ) ;
2006-12-06 17:25:32 -06:00
}
2012-01-15 23:36:13 -06:00
if ( is_suffix_used )
* is_suffix_used = absolute > 0 ;
2012-01-15 23:36:12 -06:00
return res ;
2006-12-06 17:25:32 -06:00
}
2009-11-04 07:30:31 -06:00
/*
* Print the message MESG , then read an integer in LOW . . HIGH .
* If the user hits Enter , DFLT is returned , provided that is in LOW . . HIGH .
* Answers like + 10 are interpreted as offsets from BASE .
*
* There is no default if DFLT is not between LOW and HIGH .
*/
unsigned int
2012-06-03 13:15:17 -05:00
read_int ( struct fdisk_context * cxt ,
unsigned int low , unsigned int dflt , unsigned int high ,
2009-11-04 07:30:31 -06:00
unsigned int base , char * mesg )
{
2012-06-03 13:15:17 -05:00
return read_int_with_suffix ( cxt , low , dflt , high , base , mesg , NULL ) ;
2009-11-04 07:30:31 -06:00
}
2012-12-11 08:08:06 -06:00
static void toggle_dos_compatibility_flag ( struct fdisk_context * cxt )
{
struct fdisk_label * lb = fdisk_context_get_label ( cxt , " dos " ) ;
int flag ;
if ( ! lb )
return ;
flag = ! fdisk_dos_is_compatible ( lb ) ;
if ( flag )
2010-06-16 03:52:20 -05:00
printf ( _ ( " DOS Compatibility flag is set (DEPRECATED!) \n " ) ) ;
2009-11-03 04:28:55 -06:00
else
2006-12-06 17:25:39 -06:00
printf ( _ ( " DOS Compatibility flag is not set \n " ) ) ;
2009-11-03 04:28:55 -06:00
2012-12-11 08:08:06 -06:00
fdisk_dos_enable_compatible ( lb , flag ) ;
if ( fdisk_is_disklabel ( cxt , DOS ) )
fdisk_reset_alignment ( cxt ) ;
2006-12-06 17:25:32 -06:00
}
2012-07-23 11:15:57 -05:00
static void delete_partition ( struct fdisk_context * cxt , int partnum )
2011-11-14 07:47:19 -06:00
{
2012-07-23 11:15:57 -05:00
if ( partnum < 0 | | warn_geometry ( cxt ) )
2011-12-15 13:02:46 -06:00
return ;
2012-07-23 11:15:57 -05:00
ptes [ partnum ] . changed = 1 ;
2012-10-07 09:33:37 -05:00
if ( fdisk_delete_partition ( cxt , partnum ) ! = 0 )
printf ( _ ( " Could not delete partition %d \n " ) , partnum + 1 ) ;
else
printf ( _ ( " Partition %d is deleted \n " ) , partnum + 1 ) ;
2006-12-06 17:25:32 -06:00
}
2012-09-26 06:30:44 -05:00
static void change_partition_type ( struct fdisk_context * cxt )
2012-06-03 13:15:17 -05:00
{
2013-03-05 08:39:12 -06:00
size_t i ;
2012-09-25 03:23:36 -05:00
struct fdisk_parttype * t , * org_t ;
2006-12-06 17:25:32 -06:00
2013-01-22 06:46:55 -06:00
assert ( cxt ) ;
assert ( cxt - > label ) ;
2013-03-05 08:39:12 -06:00
if ( fdisk_ask_partnum ( cxt , & i , FALSE ) )
2006-12-06 17:26:03 -06:00
return ;
2006-12-06 17:25:35 -06:00
2012-09-25 05:12:28 -05:00
org_t = t = fdisk_get_partition_type ( cxt , i ) ;
if ( ! t )
2013-03-05 08:39:12 -06:00
printf ( _ ( " Partition %zu does not exist yet! \n " ) , i + 1 ) ;
2012-09-25 05:12:28 -05:00
2012-09-26 06:30:44 -05:00
else do {
2012-09-25 03:23:36 -05:00
t = read_partition_type ( cxt ) ;
if ( ! t )
continue ;
2012-09-26 06:30:44 -05:00
if ( fdisk_set_partition_type ( cxt , i , t ) = = 0 ) {
ptes [ i ] . changed = 1 ;
printf ( _ ( " Changed type of partition '%s' to '%s' \n " ) ,
org_t ? org_t - > name : _ ( " Unknown " ) ,
t ? t - > name : _ ( " Unknown " ) ) ;
} else {
2013-03-05 08:39:12 -06:00
printf ( _ ( " Type of partition %zu is unchanged: %s \n " ) ,
2012-09-26 06:30:44 -05:00
i + 1 ,
org_t ? org_t - > name : _ ( " Unknown " ) ) ;
2006-12-06 17:25:32 -06:00
}
2012-09-26 06:30:44 -05:00
break ;
} while ( 1 ) ;
2012-09-25 03:23:36 -05:00
fdisk_free_parttype ( t ) ;
fdisk_free_parttype ( org_t ) ;
2006-12-06 17:25:32 -06:00
}
2006-12-06 17:25:43 -06:00
static void
2012-05-27 14:44:04 -05:00
list_disk_geometry ( struct fdisk_context * cxt ) {
2012-06-03 13:15:20 -05:00
unsigned long long bytes = cxt - > total_sectors * cxt - > sector_size ;
2006-12-06 17:26:03 -06:00
long megabytes = bytes / 1000000 ;
if ( megabytes < 10000 )
2012-07-26 09:04:26 -05:00
printf ( _ ( " \n Disk %s: %ld MB, %lld bytes " ) ,
2012-05-21 15:28:03 -05:00
cxt - > dev_path , megabytes , bytes ) ;
2008-08-20 16:27:50 -05:00
else {
long hectomega = ( megabytes + 50 ) / 100 ;
2012-07-26 09:04:26 -05:00
printf ( _ ( " \n Disk %s: %ld.%ld GB, %llu bytes " ) ,
2012-05-21 15:28:03 -05:00
cxt - > dev_path , hectomega / 10 , hectomega % 10 , bytes ) ;
2008-08-20 16:27:50 -05:00
}
2012-07-26 09:04:26 -05:00
printf ( _ ( " , %llu sectors \n " ) , cxt - > total_sectors ) ;
2012-12-11 08:08:06 -06:00
if ( is_dos_compatible ( cxt ) )
2012-07-26 09:04:27 -05:00
printf ( _ ( " %d heads, %llu sectors/track, %llu cylinders \n " ) ,
cxt - > geom . heads , cxt - > geom . sectors , cxt - > geom . cylinders ) ;
2012-06-03 13:15:17 -05:00
printf ( _ ( " Units = %s of %d * %ld = %ld bytes \n " ) ,
2013-02-11 09:38:20 -06:00
fdisk_context_get_unit ( cxt , PLURAL ) ,
fdisk_context_get_units_per_sector ( cxt ) ,
cxt - > sector_size ,
fdisk_context_get_units_per_sector ( cxt ) * cxt - > sector_size ) ;
2009-10-29 05:25:59 -05:00
2012-06-03 13:15:17 -05:00
printf ( _ ( " Sector size (logical/physical): %lu bytes / %lu bytes \n " ) ,
cxt - > sector_size , cxt - > phy_sector_size ) ;
2010-02-04 08:02:16 -06:00
printf ( _ ( " I/O size (minimum/optimal): %lu bytes / %lu bytes \n " ) ,
2012-06-03 13:15:17 -05:00
cxt - > min_io_size , cxt - > io_size ) ;
if ( cxt - > alignment_offset )
printf ( _ ( " Alignment offset: %lu bytes \n " ) , cxt - > alignment_offset ) ;
2012-12-04 07:58:55 -06:00
if ( fdisk_dev_has_disklabel ( cxt ) )
printf ( _ ( " Disk label type: %s \n " ) , cxt - > label - > name ) ;
2012-11-25 22:25:49 -06:00
if ( fdisk_is_disklabel ( cxt , DOS ) )
2012-06-17 11:10:07 -05:00
dos_print_mbr_id ( cxt ) ;
2007-07-06 20:32:31 -05:00
printf ( " \n " ) ;
2006-12-06 17:25:37 -06:00
}
fdisk: add GPT support
This patch allows fdisk to handle GUID partition tables, based on the latest UEFI specifications
version 2.3.1, from June 27th, 2012. The following operations are supported:
- Probing (detects both protective and hybrid MBRs)
- Writing to disk
- Listing used partitions
- Adding partitions
- Deleting partitions
- Data integrity verifications (for both headers and partitions).
A few considerations:
- Currently we do not fix invalid primary headers -- we just abort!
- Header checksums are updated upon every change (ie: add/delete partitions), this allows us
to mathematically verify the changes on-the-fly, and not only when writing to disk, like
most other related tools do.
- We are extremly picky when writing to disk, any error aborts the opeartion.
- When creating a new partition, the following GUIDs are available:
http://en.wikipedia.org/wiki/GUID_Partition_Table#Partition_type_GUIDs
For test cases, the gpt.img from libblkid tests, scsi_debug and my own hard drive (/dev/sda) were used.
For the image, all operations were tested successfully, and for /dev/sda all except write, which
was not tested - hey, I'm not suicidal!
[kzak@redhat.com: - add get/set partition type functions
- use unified on strings based table for partition types
- add partition type to table list function]
Tested-and-reviewed-by: Petr Uzel <petr.uzel@suse.cz>
Signed-off-by: Davidlohr Bueso <dave@gnu.org>
Signed-off-by: Karel Zak <kzak@redhat.com>
2012-09-27 02:50:27 -05:00
static void list_table ( struct fdisk_context * cxt , int xtra )
{
2012-11-25 22:25:49 -06:00
if ( fdisk_is_disklabel ( cxt , SUN ) ) {
2012-05-27 14:44:04 -05:00
sun_list_table ( cxt , xtra ) ;
2006-12-06 17:25:37 -06:00
return ;
}
2012-11-25 22:25:49 -06:00
if ( fdisk_is_disklabel ( cxt , SGI ) ) {
2012-05-27 14:44:04 -05:00
sgi_list_table ( cxt , xtra ) ;
2006-12-06 17:25:37 -06:00
return ;
}
2006-12-06 17:25:35 -06:00
2012-05-27 14:44:04 -05:00
list_disk_geometry ( cxt ) ;
2006-12-06 17:25:43 -06:00
2012-11-25 22:25:49 -06:00
if ( fdisk_is_disklabel ( cxt , GPT ) ) {
fdisk: add GPT support
This patch allows fdisk to handle GUID partition tables, based on the latest UEFI specifications
version 2.3.1, from June 27th, 2012. The following operations are supported:
- Probing (detects both protective and hybrid MBRs)
- Writing to disk
- Listing used partitions
- Adding partitions
- Deleting partitions
- Data integrity verifications (for both headers and partitions).
A few considerations:
- Currently we do not fix invalid primary headers -- we just abort!
- Header checksums are updated upon every change (ie: add/delete partitions), this allows us
to mathematically verify the changes on-the-fly, and not only when writing to disk, like
most other related tools do.
- We are extremly picky when writing to disk, any error aborts the opeartion.
- When creating a new partition, the following GUIDs are available:
http://en.wikipedia.org/wiki/GUID_Partition_Table#Partition_type_GUIDs
For test cases, the gpt.img from libblkid tests, scsi_debug and my own hard drive (/dev/sda) were used.
For the image, all operations were tested successfully, and for /dev/sda all except write, which
was not tested - hey, I'm not suicidal!
[kzak@redhat.com: - add get/set partition type functions
- use unified on strings based table for partition types
- add partition type to table list function]
Tested-and-reviewed-by: Petr Uzel <petr.uzel@suse.cz>
Signed-off-by: Davidlohr Bueso <dave@gnu.org>
Signed-off-by: Karel Zak <kzak@redhat.com>
2012-09-27 02:50:27 -05:00
gpt_list_table ( cxt , xtra ) ;
return ;
}
2012-11-25 22:25:49 -06:00
if ( fdisk_is_disklabel ( cxt , OSF ) ) {
2012-05-27 14:44:04 -05:00
xbsd_print_disklabel ( cxt , xtra ) ;
2006-12-06 17:25:43 -06:00
return ;
}
2013-01-21 05:01:44 -06:00
if ( fdisk_is_disklabel ( cxt , DOS ) )
dos_list_table ( cxt , xtra ) ;
2006-12-06 17:25:32 -06:00
}
2012-07-24 02:54:52 -05:00
static void verify ( struct fdisk_context * cxt )
{
2012-06-17 11:10:33 -05:00
if ( warn_geometry ( cxt ) )
2006-12-06 17:25:32 -06:00
return ;
2012-07-24 02:54:52 -05:00
fdisk_verify_disklabel ( cxt ) ;
2006-12-06 17:25:32 -06:00
}
2012-06-03 13:15:17 -05:00
void print_partition_size ( struct fdisk_context * cxt ,
int num , sector_t start , sector_t stop , int sysid )
2011-08-17 06:21:12 -05:00
{
char * str = size_to_human_string ( SIZE_SUFFIX_3LETTER | SIZE_SUFFIX_SPACE ,
2012-07-31 12:07:37 -05:00
( uint64_t ) ( stop - start + 1 ) * cxt - > sector_size ) ;
2012-09-25 03:23:36 -05:00
struct fdisk_parttype * t = fdisk_get_parttype_from_code ( cxt , sysid ) ;
printf ( _ ( " Partition %d of type %s and of size %s is set \n " ) ,
num , t ? t - > name : _ ( " Unknown " ) , str ) ;
2011-08-17 06:21:12 -05:00
free ( str ) ;
}
2012-06-03 13:15:17 -05:00
static void new_partition ( struct fdisk_context * cxt )
2012-05-06 07:10:18 -05:00
{
2013-01-18 04:43:56 -06:00
assert ( cxt ) ;
assert ( cxt - > label ) ;
2012-07-24 02:34:22 -05:00
if ( warn_geometry ( cxt ) )
2006-12-06 17:25:49 -06:00
return ;
2013-01-28 09:16:11 -06:00
fdisk_add_partition ( cxt , NULL ) ;
2006-12-06 17:25:32 -06:00
}
2012-07-23 11:47:42 -05:00
static void write_table ( struct fdisk_context * cxt )
{
int rc ;
2006-12-06 17:25:32 -06:00
2012-07-23 11:47:42 -05:00
rc = fdisk_write_disklabel ( cxt ) ;
if ( rc )
err ( EXIT_FAILURE , _ ( " cannot write disk label " ) ) ;
2006-12-06 17:25:32 -06:00
2006-12-06 17:25:39 -06:00
printf ( _ ( " The partition table has been altered! \n \n " ) ) ;
2012-05-27 14:44:04 -05:00
reread_partition_table ( cxt , 1 ) ;
2006-12-06 17:25:41 -06:00
}
void
2012-05-27 14:44:04 -05:00
reread_partition_table ( struct fdisk_context * cxt , int leave ) {
2006-12-06 17:25:41 -06:00
int i ;
2007-09-03 17:10:16 -05:00
struct stat statbuf ;
2006-12-06 17:25:32 -06:00
2012-05-21 15:28:03 -05:00
i = fstat ( cxt - > dev_fd , & statbuf ) ;
2007-09-03 17:10:16 -05:00
if ( i = = 0 & & S_ISBLK ( statbuf . st_mode ) ) {
sync ( ) ;
2008-07-23 17:46:05 -05:00
# ifdef BLKRRPART
printf ( _ ( " Calling ioctl() to re-read partition table. \n " ) ) ;
2012-05-21 15:28:03 -05:00
i = ioctl ( cxt - > dev_fd , BLKRRPART ) ;
2008-07-23 17:46:05 -05:00
# else
errno = ENOSYS ;
i = 1 ;
# endif
2006-12-06 17:25:33 -06:00
}
2006-12-06 17:25:49 -06:00
if ( i ) {
2011-09-22 05:12:37 -05:00
printf ( _ ( " \n WARNING: Re-reading the partition table failed with error %d: %m. \n "
2008-09-16 06:08:12 -05:00
" The kernel still uses the old table. The new table will be used at \n "
" the next reboot or after you run partprobe(8) or kpartx(8) \n " ) ,
2011-09-22 05:12:37 -05:00
errno ) ;
2006-12-06 17:25:49 -06:00
}
2006-12-06 17:25:32 -06:00
2006-12-06 17:25:41 -06:00
if ( leave ) {
2012-05-21 15:28:03 -05:00
if ( fsync ( cxt - > dev_fd ) | | close ( cxt - > dev_fd ) ) {
2006-12-06 17:26:30 -06:00
fprintf ( stderr , _ ( " \n Error closing file \n " ) ) ;
exit ( 1 ) ;
}
2006-12-06 17:25:41 -06:00
printf ( _ ( " Syncing disks. \n " ) ) ;
sync ( ) ;
exit ( ! ! i ) ;
}
2006-12-06 17:25:32 -06:00
}
# define MAX_PER_LINE 16
2006-12-06 17:25:43 -06:00
static void
2012-06-03 13:15:17 -05:00
print_buffer ( struct fdisk_context * cxt , unsigned char pbuffer [ ] ) {
2011-08-01 08:19:53 -05:00
unsigned int i , l ;
2006-12-06 17:25:32 -06:00
2012-06-03 13:15:17 -05:00
for ( i = 0 , l = 0 ; i < cxt - > sector_size ; i + + , l + + ) {
2006-12-06 17:25:32 -06:00
if ( l = = 0 )
printf ( " 0x%03X: " , i ) ;
2007-05-30 10:10:43 -05:00
printf ( " %02X " , pbuffer [ i ] ) ;
2006-12-06 17:25:32 -06:00
if ( l = = MAX_PER_LINE - 1 ) {
printf ( " \n " ) ;
l = - 1 ;
}
}
if ( l > 0 )
printf ( " \n " ) ;
printf ( " \n " ) ;
}
2012-06-03 13:15:17 -05:00
static void print_raw ( struct fdisk_context * cxt )
{
2013-01-22 06:46:55 -06:00
size_t i ;
assert ( cxt ) ;
assert ( cxt - > label ) ;
2006-12-06 17:25:32 -06:00
2012-06-03 13:15:17 -05:00
printf ( _ ( " Device: %s \n " ) , cxt - > dev_path ) ;
2012-11-25 22:25:49 -06:00
if ( fdisk_is_disklabel ( cxt , SUN ) | |
fdisk_is_disklabel ( cxt , SGI ) | |
fdisk_is_disklabel ( cxt , GPT ) )
2012-07-23 07:24:25 -05:00
print_buffer ( cxt , cxt - > firstsector ) ;
2013-01-22 06:46:55 -06:00
else for ( i = 3 ; i < cxt - > label - > nparts_max ; i + + )
2012-06-03 13:15:17 -05:00
print_buffer ( cxt , ptes [ i ] . sectorbuffer ) ;
2006-12-06 17:25:32 -06:00
}
2012-05-21 15:28:03 -05:00
static void __attribute__ ( ( __noreturn__ ) ) handle_quit ( struct fdisk_context * cxt )
2012-05-20 11:11:21 -05:00
{
2012-05-21 15:28:03 -05:00
fdisk_free_context ( cxt ) ;
2012-05-20 11:11:21 -05:00
printf ( " \n " ) ;
exit ( EXIT_SUCCESS ) ;
}
2006-12-06 17:25:43 -06:00
static void
2012-05-27 14:44:04 -05:00
expert_command_prompt ( struct fdisk_context * cxt )
2011-11-11 04:12:08 -06:00
{
2006-12-06 17:25:43 -06:00
char c ;
2013-03-05 08:39:12 -06:00
size_t n ;
2006-12-06 17:25:43 -06:00
2013-01-22 06:46:55 -06:00
assert ( cxt ) ;
2006-12-06 17:25:32 -06:00
while ( 1 ) {
2013-01-22 06:46:55 -06:00
assert ( cxt - > label ) ;
2006-12-06 17:25:32 -06:00
putchar ( ' \n ' ) ;
2013-01-18 09:11:40 -06:00
c = tolower ( read_char ( cxt , _ ( " Expert command (m for help): " ) ) ) ;
2006-12-06 17:25:43 -06:00
switch ( c ) {
2006-12-06 17:25:35 -06:00
case ' a ' :
2012-11-25 22:25:49 -06:00
if ( fdisk_is_disklabel ( cxt , SUN ) )
2013-02-22 08:34:04 -06:00
fdisk_sun_set_alt_cyl ( cxt ) ;
2006-12-06 17:25:35 -06:00
break ;
case ' b ' :
2013-03-05 08:39:12 -06:00
if ( fdisk_is_disklabel ( cxt , DOS ) & &
fdisk_ask_partnum ( cxt , & n , FALSE ) = = 0 )
dos_move_begin ( cxt , n ) ;
2006-12-06 17:25:35 -06:00
break ;
case ' c ' :
2012-12-03 08:32:16 -06:00
user_cylinders = read_int ( cxt , 1 , cxt - > geom . cylinders , 1048576 , 0 ,
2006-12-06 17:25:43 -06:00
_ ( " Number of cylinders " ) ) ;
2012-12-06 05:12:41 -06:00
fdisk_override_geometry ( cxt , user_cylinders , user_heads , user_sectors ) ;
2012-11-25 22:25:49 -06:00
if ( fdisk_is_disklabel ( cxt , SUN ) )
2013-02-22 08:34:04 -06:00
fdisk_sun_set_ncyl ( cxt , cxt - > geom . cylinders ) ;
2006-12-06 17:25:35 -06:00
break ;
case ' d ' :
2012-06-03 13:15:17 -05:00
print_raw ( cxt ) ;
2006-12-06 17:25:35 -06:00
break ;
case ' e ' :
2012-11-25 22:25:49 -06:00
if ( fdisk_is_disklabel ( cxt , SGI ) )
2006-12-06 17:25:37 -06:00
sgi_set_xcyl ( ) ;
2012-11-25 22:25:49 -06:00
else if ( fdisk_is_disklabel ( cxt , SUN ) )
2013-02-22 08:34:04 -06:00
fdisk_sun_set_xcyl ( cxt ) ;
2006-12-06 17:25:56 -06:00
else
2012-11-25 22:25:49 -06:00
if ( fdisk_is_disklabel ( cxt , DOS ) )
2013-01-21 05:25:30 -06:00
dos_list_table_expert ( cxt , 1 ) ;
2006-12-06 17:25:37 -06:00
break ;
2006-12-06 17:25:43 -06:00
case ' f ' :
2012-11-25 22:25:49 -06:00
if ( fdisk_is_disklabel ( cxt , DOS ) )
2013-01-22 06:46:55 -06:00
dos_fix_partition_table_order ( cxt ) ;
2006-12-06 17:25:43 -06:00
break ;
2006-12-06 17:25:37 -06:00
case ' g ' :
2012-07-24 07:15:08 -05:00
fdisk_create_disklabel ( cxt , " sgi " ) ;
2006-12-06 17:25:35 -06:00
break ;
case ' h ' :
2012-12-03 08:32:16 -06:00
user_heads = read_int ( cxt , 1 , cxt - > geom . heads , 256 , 0 ,
2006-12-06 17:25:39 -06:00
_ ( " Number of heads " ) ) ;
2012-12-06 05:12:41 -06:00
fdisk_override_geometry ( cxt , user_cylinders , user_heads , user_sectors ) ;
2006-12-06 17:25:35 -06:00
break ;
case ' i ' :
2012-11-25 22:25:49 -06:00
if ( fdisk_is_disklabel ( cxt , SUN ) )
2013-02-22 08:34:04 -06:00
fdisk_sun_set_ilfact ( cxt ) ;
2012-11-25 22:25:49 -06:00
else if ( fdisk_is_disklabel ( cxt , DOS ) )
2012-06-17 11:10:07 -05:00
dos_set_mbr_id ( cxt ) ;
2006-12-06 17:25:35 -06:00
break ;
case ' o ' :
2012-11-25 22:25:49 -06:00
if ( fdisk_is_disklabel ( cxt , SUN ) )
2013-02-22 08:34:04 -06:00
fdisk_sun_set_rspeed ( cxt ) ;
2006-12-06 17:25:35 -06:00
break ;
case ' p ' :
2012-11-25 22:25:49 -06:00
if ( fdisk_is_disklabel ( cxt , SUN ) )
2012-05-27 14:44:04 -05:00
list_table ( cxt , 1 ) ;
2006-12-06 17:25:35 -06:00
else
2013-01-21 05:25:30 -06:00
dos_list_table_expert ( cxt , 0 ) ;
2006-12-06 17:25:35 -06:00
break ;
case ' q ' :
2012-05-21 15:28:03 -05:00
handle_quit ( cxt ) ;
2006-12-06 17:25:35 -06:00
case ' r ' :
return ;
case ' s ' :
2012-12-03 08:32:16 -06:00
user_sectors = read_int ( cxt , 1 , cxt - > geom . sectors , 63 , 0 ,
2006-12-06 17:25:39 -06:00
_ ( " Number of sectors " ) ) ;
2012-12-11 08:08:06 -06:00
if ( is_dos_compatible ( cxt ) )
2006-12-06 17:25:39 -06:00
fprintf ( stderr , _ ( " Warning: setting "
2006-12-06 17:25:35 -06:00
" sector offset for DOS "
2012-07-26 09:04:25 -05:00
" compatibility \n " ) ) ;
2012-12-06 05:12:41 -06:00
fdisk_override_geometry ( cxt , user_cylinders , user_heads , user_sectors ) ;
2006-12-06 17:25:35 -06:00
break ;
case ' v ' :
2012-06-03 13:15:17 -05:00
verify ( cxt ) ;
2006-12-06 17:25:35 -06:00
break ;
case ' w ' :
2012-05-27 14:44:07 -05:00
write_table ( cxt ) ;
2006-12-06 17:25:35 -06:00
break ;
case ' y ' :
2012-11-25 22:25:49 -06:00
if ( fdisk_is_disklabel ( cxt , SUN ) )
2013-02-22 08:34:04 -06:00
fdisk_sun_set_pcylcount ( cxt ) ;
2006-12-06 17:25:35 -06:00
break ;
default :
2012-11-25 22:25:49 -06:00
print_menu ( cxt , EXPERT_MENU ) ;
2006-12-06 17:25:32 -06:00
}
}
}
2011-12-20 07:42:10 -06:00
static int is_ide_cdrom_or_tape ( char * device )
{
int fd , ret ;
2006-12-06 17:25:35 -06:00
2012-02-01 06:42:08 -06:00
if ( ( fd = open ( device , O_RDONLY ) ) < 0 )
2006-12-06 17:25:49 -06:00
return 0 ;
2011-12-20 07:42:10 -06:00
ret = blkdev_is_cdrom ( fd ) ;
2006-12-06 17:25:35 -06:00
2011-12-20 07:42:10 -06:00
close ( fd ) ;
return ret ;
2006-12-06 17:25:35 -06:00
}
2011-12-15 13:02:41 -06:00
/* Print disk geometry and partition table of a specified device (-l option) */
2012-12-11 07:41:57 -06:00
static void print_partition_table_from_option ( struct fdisk_context * cxt ,
char * device , unsigned long sector_size )
2011-12-15 13:02:40 -06:00
{
2012-12-11 07:41:57 -06:00
if ( fdisk_context_assign_device ( cxt , device , 1 ) ! = 0 ) /* read-only */
2012-07-15 03:39:57 -05:00
err ( EXIT_FAILURE , _ ( " cannot open %s " ) , device ) ;
2012-05-21 15:28:03 -05:00
2012-07-23 03:11:08 -05:00
if ( sector_size ) /* passed -b option, override autodiscovery */
2012-12-06 05:12:41 -06:00
fdisk_override_sector_size ( cxt , sector_size ) ;
2012-07-23 03:11:08 -05:00
2012-07-23 06:57:58 -05:00
if ( user_cylinders | | user_heads | | user_sectors )
2012-12-06 05:12:41 -06:00
fdisk_override_geometry ( cxt , user_cylinders ,
2012-07-23 03:11:08 -05:00
user_heads , user_sectors ) ;
2012-07-23 04:08:26 -05:00
2013-03-11 09:51:22 -05:00
if ( fdisk_dev_has_disklabel ( cxt ) )
2012-05-27 14:44:04 -05:00
list_table ( cxt , 0 ) ;
2013-03-11 09:51:22 -05:00
else
list_disk_geometry ( cxt ) ;
2006-12-06 17:25:32 -06:00
}
2006-12-06 17:26:16 -06:00
/*
* for fdisk - l :
* try all things in / proc / partitions that look like a full disk
*/
2006-12-06 17:25:43 -06:00
static void
2012-12-11 07:41:57 -06:00
print_all_partition_table_from_option ( struct fdisk_context * cxt ,
unsigned long sector_size )
2011-12-15 13:02:41 -06:00
{
2006-12-06 17:25:41 -06:00
FILE * procpt ;
2012-07-09 15:26:27 -05:00
char line [ 128 + 1 ] , ptname [ 128 + 1 ] , devname [ 256 ] ;
2008-11-13 08:37:22 -06:00
int ma , mi ;
unsigned long long sz ;
2006-12-06 17:25:41 -06:00
2010-12-16 18:28:59 -06:00
procpt = fopen ( _PATH_PROC_PARTITIONS , " r " ) ;
2006-12-06 17:25:41 -06:00
if ( procpt = = NULL ) {
2010-12-16 18:28:59 -06:00
fprintf ( stderr , _ ( " cannot open %s \n " ) , _PATH_PROC_PARTITIONS ) ;
2006-12-06 17:25:41 -06:00
return ;
}
while ( fgets ( line , sizeof ( line ) , procpt ) ) {
2009-04-29 07:24:45 -05:00
if ( sscanf ( line , " %d %d %llu %128[^ \n ] " ,
2006-12-06 17:25:41 -06:00
& ma , & mi , & sz , ptname ) ! = 4 )
continue ;
2006-12-06 17:25:46 -06:00
snprintf ( devname , sizeof ( devname ) , " /dev/%s " , ptname ) ;
2010-12-16 18:28:59 -06:00
if ( is_whole_disk ( devname ) ) {
char * cn = canonicalize_path ( devname ) ;
if ( cn ) {
2011-12-22 08:53:25 -06:00
if ( ! is_ide_cdrom_or_tape ( cn ) )
2012-12-11 07:41:57 -06:00
print_partition_table_from_option ( cxt , cn , sector_size ) ;
2010-12-16 18:28:59 -06:00
free ( cn ) ;
}
}
2006-12-06 17:25:41 -06:00
}
2006-12-06 17:25:49 -06:00
fclose ( procpt ) ;
2006-12-06 17:25:41 -06:00
}
2006-12-06 17:25:43 -06:00
static void
unknown_command ( int c ) {
printf ( _ ( " %c: unknown command \n " ) , c ) ;
2006-12-06 17:25:39 -06:00
}
2012-05-27 14:43:56 -05:00
static void print_welcome ( void )
{
printf ( _ ( " Welcome to fdisk (%s). \n \n "
" Changes will remain in memory only, until you decide to write them. \n "
" Be careful before using the write command. \n \n " ) , PACKAGE_STRING ) ;
fflush ( stdout ) ;
}
2012-05-27 14:44:04 -05:00
static void command_prompt ( struct fdisk_context * cxt )
2011-11-11 04:12:09 -06:00
{
2011-12-15 13:02:46 -06:00
int c ;
2013-03-05 08:39:12 -06:00
size_t n ;
2007-05-31 07:31:51 -05:00
2013-01-22 06:46:55 -06:00
assert ( cxt ) ;
2012-11-25 22:25:49 -06:00
if ( fdisk_is_disklabel ( cxt , OSF ) ) {
2011-11-11 04:12:09 -06:00
putchar ( ' \n ' ) ;
/* OSF label, and no DOS label */
printf ( _ ( " Detected an OSF/1 disklabel on %s, entering "
" disklabel mode. \n " ) ,
2012-05-21 15:28:03 -05:00
cxt - > dev_path ) ;
2012-05-27 14:44:04 -05:00
bsd_command_prompt ( cxt ) ;
2012-12-11 11:30:03 -06:00
2011-11-11 04:12:09 -06:00
/* If we return we may want to make an empty DOS label? */
2012-12-11 11:30:03 -06:00
fdisk_context_switch_label ( cxt , " dos " ) ;
2011-11-11 04:12:09 -06:00
}
while ( 1 ) {
2013-01-22 06:46:55 -06:00
assert ( cxt - > label ) ;
2011-11-11 04:12:09 -06:00
putchar ( ' \n ' ) ;
2013-01-18 09:11:40 -06:00
c = tolower ( read_char ( cxt , _ ( " Command (m for help): " ) ) ) ;
2011-11-11 04:12:09 -06:00
switch ( c ) {
case ' a ' :
2013-03-05 08:39:12 -06:00
if ( fdisk_is_disklabel ( cxt , DOS ) & &
fdisk_ask_partnum ( cxt , & n , FALSE ) = = 0 )
fdisk_partition_toggle_flag ( cxt , n , DOS_FLAG_ACTIVE ) ;
else if ( fdisk_is_disklabel ( cxt , SUN ) & &
fdisk_ask_partnum ( cxt , & n , FALSE ) = = 0 )
fdisk_partition_toggle_flag ( cxt , n , SUN_FLAG_UNMNT ) ;
else if ( fdisk_is_disklabel ( cxt , SGI ) & &
fdisk_ask_partnum ( cxt , & n , FALSE ) = = 0 )
fdisk_partition_toggle_flag ( cxt , n , SGI_FLAG_BOOT ) ;
2011-11-11 04:12:09 -06:00
else
unknown_command ( c ) ;
break ;
case ' b ' :
2012-11-25 22:25:49 -06:00
if ( fdisk_is_disklabel ( cxt , SGI ) )
2012-06-17 11:10:07 -05:00
sgi_set_bootfile ( cxt ) ;
2012-11-25 22:25:49 -06:00
else if ( fdisk_is_disklabel ( cxt , DOS ) ) {
2013-03-05 08:14:04 -06:00
struct fdisk_context * bsd ;
bsd = fdisk_new_nested_context ( cxt , " bsd " ) ;
if ( bsd )
bsd_command_prompt ( bsd ) ;
fdisk_free_context ( bsd ) ;
2011-11-09 12:04:12 -06:00
} else
unknown_command ( c ) ;
2011-11-11 04:12:09 -06:00
break ;
case ' c ' :
2012-11-25 22:25:49 -06:00
if ( fdisk_is_disklabel ( cxt , DOS ) )
2012-06-03 13:15:17 -05:00
toggle_dos_compatibility_flag ( cxt ) ;
2013-03-05 08:39:12 -06:00
else if ( fdisk_is_disklabel ( cxt , SUN ) & &
fdisk_ask_partnum ( cxt , & n , FALSE ) = = 0 )
fdisk_partition_toggle_flag ( cxt , n , SUN_FLAG_RONLY ) ;
else if ( fdisk_is_disklabel ( cxt , SGI ) & &
fdisk_ask_partnum ( cxt , & n , FALSE ) = = 0 )
fdisk_partition_toggle_flag ( cxt , n , SGI_FLAG_SWAP ) ;
2011-11-11 04:12:09 -06:00
else
unknown_command ( c ) ;
break ;
case ' d ' :
2013-03-05 08:39:12 -06:00
if ( fdisk_ask_partnum ( cxt , & n , FALSE ) = = 0 )
delete_partition ( cxt , n ) ;
2011-11-11 04:12:09 -06:00
break ;
2012-10-27 12:23:47 -05:00
case ' g ' :
fdisk_create_disklabel ( cxt , " gpt " ) ;
break ;
2013-02-07 05:18:27 -06:00
case ' G ' :
fdisk_create_disklabel ( cxt , " sgi " ) ;
break ;
2011-11-11 04:12:09 -06:00
case ' i ' :
2012-11-25 22:25:49 -06:00
if ( fdisk_is_disklabel ( cxt , SGI ) )
2012-06-17 11:10:07 -05:00
create_sgiinfo ( cxt ) ;
2011-11-11 04:12:09 -06:00
else
unknown_command ( c ) ;
2012-01-31 14:06:42 -06:00
break ;
2011-11-11 04:12:09 -06:00
case ' l ' :
2012-09-24 06:24:09 -05:00
list_partition_types ( cxt ) ;
2011-11-11 04:12:09 -06:00
break ;
case ' m ' :
2012-11-25 22:25:49 -06:00
print_menu ( cxt , MAIN_MENU ) ;
2011-11-11 04:12:09 -06:00
break ;
case ' n ' :
2012-06-03 13:15:17 -05:00
new_partition ( cxt ) ;
2011-11-11 04:12:09 -06:00
break ;
case ' o ' :
2012-07-24 07:15:08 -05:00
fdisk_create_disklabel ( cxt , " dos " ) ;
2011-11-11 04:12:09 -06:00
break ;
case ' p ' :
2012-05-27 14:44:04 -05:00
list_table ( cxt , 0 ) ;
2011-11-11 04:12:09 -06:00
break ;
case ' q ' :
2012-05-21 15:28:03 -05:00
handle_quit ( cxt ) ;
2011-11-11 04:12:09 -06:00
case ' s ' :
2012-07-24 07:15:08 -05:00
fdisk_create_disklabel ( cxt , " sun " ) ;
2011-11-11 04:12:09 -06:00
break ;
case ' t ' :
2012-09-26 06:30:44 -05:00
change_partition_type ( cxt ) ;
2011-11-11 04:12:09 -06:00
break ;
case ' u ' :
2013-02-11 09:38:20 -06:00
toggle_units ( cxt ) ;
2011-11-11 04:12:09 -06:00
break ;
case ' v ' :
2012-06-03 13:15:17 -05:00
verify ( cxt ) ;
2011-11-11 04:12:09 -06:00
break ;
case ' w ' :
2012-05-27 14:44:07 -05:00
write_table ( cxt ) ;
2011-11-11 04:12:09 -06:00
break ;
case ' x ' :
2012-05-27 14:44:04 -05:00
expert_command_prompt ( cxt ) ;
2011-11-11 04:12:09 -06:00
break ;
default :
unknown_command ( c ) ;
2012-11-25 22:25:49 -06:00
print_menu ( cxt , MAIN_MENU ) ;
2011-11-11 04:12:09 -06:00
}
}
}
2007-05-31 07:31:51 -05:00
2012-05-27 14:44:13 -05:00
static sector_t get_dev_blocks ( char * dev )
2012-05-21 14:23:27 -05:00
{
int fd ;
2012-05-27 14:44:13 -05:00
sector_t size ;
2012-05-21 14:23:27 -05:00
if ( ( fd = open ( dev , O_RDONLY ) ) < 0 )
2012-07-15 03:39:57 -05:00
err ( EXIT_FAILURE , _ ( " cannot open %s " ) , dev ) ;
2012-05-27 14:44:04 -05:00
if ( blkdev_get_sectors ( fd , & size ) = = - 1 ) {
close ( fd ) ;
err ( EXIT_FAILURE , _ ( " BLKGETSIZE ioctl failed on %s " ) , dev ) ;
}
2012-05-21 14:23:27 -05:00
close ( fd ) ;
return size / 2 ;
}
2012-05-20 11:11:26 -05:00
int main ( int argc , char * * argv )
{
2012-05-21 14:23:27 -05:00
int c , optl = 0 , opts = 0 ;
2012-06-03 13:15:17 -05:00
unsigned long sector_size = 0 ;
2012-12-11 07:41:57 -06:00
struct fdisk_context * cxt ;
2012-12-11 08:08:06 -06:00
struct fdisk_label * lb ;
2006-12-06 17:25:35 -06:00
2006-12-06 17:25:39 -06:00
setlocale ( LC_ALL , " " ) ;
bindtextdomain ( PACKAGE , LOCALEDIR ) ;
textdomain ( PACKAGE ) ;
2012-04-04 13:02:04 -05:00
atexit ( close_stdout ) ;
2006-12-06 17:25:35 -06:00
2012-12-11 07:41:57 -06:00
fdisk_init_debug ( 0 ) ;
cxt = fdisk_new_context ( ) ;
if ( ! cxt )
err ( EXIT_FAILURE , _ ( " failed to allocate libfdisk context " ) ) ;
2013-01-28 09:16:11 -06:00
fdisk_context_set_ask ( cxt , ask_callback , NULL ) ;
2010-06-16 03:52:20 -05:00
while ( ( c = getopt ( argc , argv , " b:c::C:hH:lsS:u::vV " ) ) ! = - 1 ) {
2006-12-06 17:25:35 -06:00
switch ( c ) {
case ' b ' :
2006-12-06 17:26:02 -06:00
/* Ugly: this sector size is really per device,
so cannot be combined with multiple disks ,
and te same goes for the C / H / S options .
*/
2012-05-15 10:43:49 -05:00
sector_size = strtou32_or_err ( optarg , _ ( " invalid sector size argument " ) ) ;
2006-12-06 17:25:37 -06:00
if ( sector_size ! = 512 & & sector_size ! = 1024 & &
2009-03-09 03:52:08 -05:00
sector_size ! = 2048 & & sector_size ! = 4096 )
2011-01-23 15:51:20 -06:00
usage ( stderr ) ;
2006-12-06 17:25:35 -06:00
break ;
2006-12-06 17:26:02 -06:00
case ' C ' :
2012-05-15 10:43:49 -05:00
user_cylinders = strtou32_or_err ( optarg , _ ( " invalid cylinders argument " ) ) ;
2006-12-06 17:26:02 -06:00
break ;
2010-02-15 07:39:30 -06:00
case ' c ' :
2012-12-11 08:08:06 -06:00
if ( optarg ) {
2013-02-22 08:34:04 -06:00
/* this setting is independent on the current
* actively used label */
2012-12-11 08:08:06 -06:00
lb = fdisk_context_get_label ( cxt , " dos " ) ;
if ( ! lb )
err ( EXIT_FAILURE , _ ( " not found DOS label driver " ) ) ;
if ( strcmp ( optarg , " =dos " ) = = 0 )
fdisk_dos_enable_compatible ( lb , TRUE ) ;
else if ( strcmp ( optarg , " =nondos " ) = = 0 )
fdisk_dos_enable_compatible ( lb , FALSE ) ;
else
usage ( stderr ) ;
}
/* use default if no optarg specified */
2010-02-15 07:39:30 -06:00
break ;
2006-12-06 17:26:02 -06:00
case ' H ' :
2012-05-15 10:43:49 -05:00
user_heads = strtou32_or_err ( optarg , _ ( " invalid heads argument " ) ) ;
if ( user_heads > 256 )
2006-12-06 17:26:02 -06:00
user_heads = 0 ;
break ;
case ' S ' :
2012-05-15 10:43:49 -05:00
user_sectors = strtou32_or_err ( optarg , _ ( " invalid sectors argument " ) ) ;
if ( user_sectors > = 64 )
2006-12-06 17:26:02 -06:00
user_sectors = 0 ;
break ;
2006-12-06 17:25:35 -06:00
case ' l ' :
optl = 1 ;
break ;
case ' s ' :
opts = 1 ;
break ;
case ' u ' :
2013-02-11 09:38:20 -06:00
if ( optarg & & * optarg = = ' = ' )
optarg + + ;
if ( fdisk_context_set_unit ( cxt , optarg ) ! = 0 )
2011-01-23 15:51:20 -06:00
usage ( stderr ) ;
2006-12-06 17:25:35 -06:00
break ;
2006-12-06 17:25:43 -06:00
case ' V ' :
2006-12-06 17:25:35 -06:00
case ' v ' :
2012-04-23 05:15:15 -05:00
printf ( UTIL_LINUX_VERSION ) ;
return EXIT_SUCCESS ;
2012-05-20 11:11:26 -05:00
case ' h ' :
usage ( stdout ) ;
2006-12-06 17:25:35 -06:00
default :
2011-01-23 15:51:20 -06:00
usage ( stderr ) ;
2006-12-06 17:25:35 -06:00
}
2006-12-06 17:25:32 -06:00
}
2006-12-06 17:25:35 -06:00
2012-05-21 15:32:25 -05:00
2012-06-03 12:47:44 -05:00
if ( sector_size & & argc - optind ! = 1 )
2006-12-06 17:25:39 -06:00
printf ( _ ( " Warning: the -b (set sector size) option should "
" be used with one specified device \n " ) ) ;
2006-12-06 17:25:35 -06:00
if ( optl ) {
nowarn = 1 ;
if ( argc > optind ) {
int k ;
2006-12-06 17:26:16 -06:00
for ( k = optind ; k < argc ; k + + )
2012-12-11 07:41:57 -06:00
print_partition_table_from_option ( cxt , argv [ k ] , sector_size ) ;
2011-12-15 13:02:41 -06:00
} else
2012-12-11 07:41:57 -06:00
print_all_partition_table_from_option ( cxt , sector_size ) ;
2012-06-03 13:15:30 -05:00
exit ( EXIT_SUCCESS ) ;
2006-12-06 17:25:35 -06:00
}
if ( opts ) {
2012-05-21 14:23:27 -05:00
/* print partition size for one or more devices */
int i , ndevs = argc - optind ;
if ( ndevs < = 0 )
2011-01-23 15:51:20 -06:00
usage ( stderr ) ;
2006-12-06 17:25:35 -06:00
2012-05-21 14:23:27 -05:00
for ( i = optind ; i < argc ; i + + ) {
if ( ndevs = = 1 )
printf ( " %llu \n " , get_dev_blocks ( argv [ i ] ) ) ;
2006-12-06 17:25:35 -06:00
else
2012-05-21 14:23:27 -05:00
printf ( " %s: %llu \n " , argv [ i ] , get_dev_blocks ( argv [ i ] ) ) ;
2006-12-06 17:25:32 -06:00
}
2012-05-21 14:23:27 -05:00
exit ( EXIT_SUCCESS ) ;
2006-12-06 17:25:32 -06:00
}
2012-07-15 01:58:51 -05:00
if ( argc - optind ! = 1 )
2011-01-23 15:51:20 -06:00
usage ( stderr ) ;
2006-12-06 17:25:39 -06:00
2012-12-11 07:41:57 -06:00
if ( fdisk_context_assign_device ( cxt , argv [ optind ] , 0 ) ! = 0 )
2012-07-15 03:39:57 -05:00
err ( EXIT_FAILURE , _ ( " cannot open %s " ) , argv [ optind ] ) ;
2012-07-23 03:11:08 -05:00
2012-07-15 01:58:51 -05:00
if ( sector_size ) /* passed -b option, override autodiscovery */
2012-12-06 05:12:41 -06:00
fdisk_override_sector_size ( cxt , sector_size ) ;
2012-07-23 03:11:08 -05:00
2012-07-23 06:57:58 -05:00
if ( user_cylinders | | user_heads | | user_sectors )
2012-12-06 05:12:41 -06:00
fdisk_override_geometry ( cxt , user_cylinders ,
2012-07-23 06:57:58 -05:00
user_heads , user_sectors ) ;
2012-07-15 01:58:51 -05:00
2012-05-27 14:43:56 -05:00
print_welcome ( ) ;
2011-11-11 04:12:09 -06:00
2012-07-23 03:56:06 -05:00
if ( ! fdisk_dev_has_disklabel ( cxt ) ) {
fprintf ( stderr ,
_ ( " Device does not contain a recognized partition table \n " ) ) ;
2012-07-24 03:31:32 -05:00
fdisk_create_disklabel ( cxt , NULL ) ;
2012-07-23 03:56:06 -05:00
}
2006-12-06 17:25:32 -06:00
2012-05-27 14:44:04 -05:00
command_prompt ( cxt ) ;
2011-08-16 17:19:04 -05:00
2012-12-11 07:41:57 -06:00
fdisk_free_context ( cxt ) ;
2006-12-06 17:25:37 -06:00
return 0 ;
2006-12-06 17:25:32 -06:00
}