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"
# include "fdiskaixlabel.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
2007-05-31 07:31:51 -05:00
# include "gpt.h"
2012-05-02 07:05:51 -05:00
int MBRbuffer_changed ;
2006-12-06 17:25:32 -06:00
# define hex_val(c) ({ \
char _c = ( c ) ; \
isdigit ( _c ) ? _c - ' 0 ' : \
tolower ( _c ) + 10 - ' a ' ; \
} )
# define sector(s) ((s) & 0x3f)
# define cylinder(s, c) ((c) | (((s) & 0xc0) << 2))
2012-11-25 22:25:49 -06:00
# define fdisk_is_disklabel(c, x) fdisk_dev_is_disklabel(c, FDISK_DISKLABEL_ ## x)
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 [ ] = {
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 } } ,
{ ' a ' , N_ ( " select bootable partition " ) , { FDISK_DISKLABEL_SGI , 0 } } ,
{ ' a ' , N_ ( " change number of alternate cylinders " ) , { 0 , FDISK_DISKLABEL_SUN } } ,
{ ' b ' , N_ ( " edit bsd disklabel " ) , { FDISK_DISKLABEL_DOS , 0 } } ,
{ ' b ' , N_ ( " edit bootfile entry " ) , { FDISK_DISKLABEL_SGI , 0 } } ,
{ ' b ' , N_ ( " move beginning of data in a partition " ) , { 0 , FDISK_DISKLABEL_DOS } } ,
{ ' c ' , N_ ( " toggle the dos compatibility flag " ) , { FDISK_DISKLABEL_DOS , 0 } } ,
{ ' c ' , N_ ( " toggle the mountable flag " ) , { FDISK_DISKLABEL_SUN , 0 } } ,
{ ' c ' , N_ ( " select sgi swap partition " ) , { FDISK_DISKLABEL_SGI , 0 } } ,
{ ' c ' , N_ ( " change number of cylinders " ) , { 0 , FDISK_DISKLABEL_DOS | FDISK_DISKLABEL_SUN } } ,
{ ' 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_ ( " list extended partitions " ) , { 0 , FDISK_DISKLABEL_DOS } } ,
{ ' e ' , N_ ( " edit drive data " ) , { FDISK_DISKLABEL_OSF , 0 } } ,
{ ' f ' , N_ ( " fix partition order " ) , { 0 , FDISK_DISKLABEL_DOS } } ,
{ ' g ' , N_ ( " create an IRIX (SGI) partition table " ) , { 0 , FDISK_DISKLABEL_ANY } } ,
{ ' g ' , N_ ( " create a new empty GPT partition table " ) , { ~ FDISK_DISKLABEL_OSF , 0 } } ,
{ ' 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_ ( " create a new empty DOS partition table " ) , { ~ FDISK_DISKLABEL_OSF , 0 } } ,
{ ' o ' , N_ ( " change rotation speed (rpm) " ) , { 0 , FDISK_DISKLABEL_SUN } } ,
{ ' 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_ ( " create a new empty Sun disklabel " ) , { ~ FDISK_DISKLABEL_OSF , 0 } } ,
{ ' s ' , N_ ( " change number of sectors/track " ) , { 0 , FDISK_DISKLABEL_DOS | FDISK_DISKLABEL_SUN } } ,
{ ' 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 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 } } ,
{ ' w ' , N_ ( " write disklabel to disk " ) , { FDISK_DISKLABEL_OSF , 0 } } ,
{ ' 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
2012-05-21 15:28:03 -05:00
int nowarn = 0 , /* no warnings for fdisk -l/-s */
2010-06-15 06:13:05 -05:00
dos_compatible_flag = 0 , /* disabled by default */
2006-12-06 17:25:32 -06:00
partitions = 4 ; /* maximum partition + 1 */
2006-12-06 17:26:12 -06:00
unsigned int user_cylinders , user_heads , user_sectors ;
2012-06-17 11:10:33 -05:00
sector_t sector_offset = 1 ;
unsigned int units_per_sector = 1 , display_in_cyl_units = 0 ;
2011-07-03 05:01:21 -05:00
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 ;
}
void
set_all_unchanged ( void ) {
int i ;
for ( i = 0 ; i < MAXIMUM_PARTS ; i + + )
ptes [ i ] . changed = 0 ;
}
void
set_changed ( int i ) {
ptes [ i ] . changed = 1 ;
}
2006-12-06 17:26:24 -06:00
static int
is_garbage_table ( void ) {
int i ;
for ( i = 0 ; i < 4 ; i + + ) {
struct pte * pe = & ptes [ i ] ;
struct partition * p = pe - > part_table ;
if ( p - > boot_ind ! = 0 & & p - > boot_ind ! = 0x80 )
return 1 ;
}
return 0 ;
}
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 ;
2006-12-06 17:25:32 -06:00
2011-11-09 12:04:12 -06:00
puts ( _ ( " Command action " ) ) ;
for ( i = 0 ; i < ARRAY_SIZE ( menulist ) ; i + + )
2012-11-25 22:25:49 -06:00
if ( menulist [ i ] . label [ menu ] & cxt - > disklabel )
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 ;
2006-12-06 17:25:32 -06:00
int i ;
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 ;
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 >
*/
unsigned int last [ 4 ] , done = 0 , next = 0 , size ;
2010-03-09 02:21:35 -06:00
2012-09-24 06:24:09 -05:00
for ( i = 0 ; types [ i ] . name ; i + + ) ;
size = i ;
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 ;
printf ( " %c%2x " , i ? ' ' : ' \n ' , t - > type ) ;
ret = mbsalign ( _ ( t - > name ) , name , sizeof ( name ) ,
& width , MBS_ALIGN_LEFT , 0 ) ;
if ( ret = = ( size_t ) - 1 | | ret > = sizeof ( name ) )
printf ( " %-15.15s " , _ ( t - > name ) ) ;
else
fputs ( name , stdout ) ;
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 ;
for ( i = 0 , t = types ; t - > name ; t + + , i + + )
printf ( " %3d %-30s %s \n " , i + 1 , t - > name , t - > typestr ) ;
}
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 ;
}
2009-11-04 09:15:48 -06:00
static int
2012-06-03 13:15:17 -05:00
lba_is_aligned ( struct fdisk_context * cxt , sector_t lba )
2009-11-04 09:15:48 -06:00
{
2012-06-03 13:15:17 -05:00
unsigned int granularity = max ( cxt - > phy_sector_size , cxt - > min_io_size ) ;
2012-07-23 16:09:41 -05:00
unsigned long long offset ;
2012-07-26 09:04:24 -05:00
if ( cxt - > grain > granularity )
granularity = cxt - > grain ;
2012-07-23 16:09:41 -05:00
offset = ( lba * cxt - > sector_size ) & ( granularity - 1 ) ;
return ! ( ( granularity + cxt - > alignment_offset - offset ) & ( granularity - 1 ) ) ;
}
static int
lba_is_phy_aligned ( struct fdisk_context * cxt , unsigned long long lba )
{
unsigned int granularity = max ( cxt - > phy_sector_size , cxt - > min_io_size ) ;
unsigned long long offset = ( lba * cxt - > sector_size ) & ( granularity - 1 ) ;
2009-11-04 09:15:48 -06:00
2012-06-03 13:15:17 -05:00
return ! ( ( granularity + cxt - > alignment_offset - offset ) & ( granularity - 1 ) ) ;
2009-11-04 09:15:48 -06:00
}
2012-06-03 13:15:17 -05:00
sector_t align_lba ( struct fdisk_context * cxt , sector_t lba , int direction )
2009-11-04 09:15:48 -06:00
{
2012-05-27 14:44:13 -05:00
sector_t res ;
2009-11-04 09:15:48 -06:00
2012-06-03 13:15:17 -05:00
if ( lba_is_aligned ( cxt , lba ) )
2010-02-12 14:43:03 -06:00
res = lba ;
else {
2012-07-26 09:04:24 -05:00
sector_t sects_in_phy = cxt - > grain / cxt - > sector_size ;
2010-02-04 06:43:37 -06:00
2010-02-12 14:43:03 -06:00
if ( lba < sector_offset )
res = sector_offset ;
2009-11-04 09:15:48 -06:00
2010-02-12 14:43:03 -06:00
else if ( direction = = ALIGN_UP )
res = ( ( lba + sects_in_phy ) / sects_in_phy ) * sects_in_phy ;
2009-11-04 09:15:48 -06:00
2010-02-12 14:43:03 -06:00
else if ( direction = = ALIGN_DOWN )
res = ( lba / sects_in_phy ) * sects_in_phy ;
2009-11-04 09:15:48 -06:00
2010-02-12 14:43:03 -06:00
else /* ALIGN_NEAREST */
res = ( ( lba + sects_in_phy / 2 ) / sects_in_phy ) * sects_in_phy ;
2009-11-04 09:15:48 -06:00
2012-06-03 13:15:17 -05:00
if ( cxt - > alignment_offset & & ! lba_is_aligned ( cxt , res ) & &
res > cxt - > alignment_offset / cxt - > sector_size ) {
2010-02-12 14:43:03 -06:00
/*
* apply alignment_offset
*
* On disk with alignment compensation physical blocks starts
* at LBA < 0 ( usually LBA - 1 ) . It means we have to move LBA
* according the offset to be on the physical boundary .
*/
/* fprintf(stderr, "LBA: %llu apply alignment_offset\n", res); */
2012-06-03 13:15:17 -05:00
res - = ( max ( cxt - > phy_sector_size , cxt - > min_io_size ) -
cxt - > alignment_offset ) / cxt - > sector_size ;
2010-02-15 07:06:56 -06:00
if ( direction = = ALIGN_UP & & res < lba )
res + = sects_in_phy ;
2010-02-12 14:43:03 -06:00
}
}
2010-02-04 06:43:37 -06:00
2009-11-04 09:15:48 -06:00
return res ;
}
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-17 11:10:33 -05:00
void update_units ( struct fdisk_context * cxt )
2006-12-06 17:25:32 -06:00
{
2012-06-17 11:10:33 -05:00
int cyl_units = cxt - > geom . heads * cxt - > geom . sectors ;
2006-12-06 17:25:37 -06:00
2006-12-06 17:25:39 -06:00
if ( display_in_cyl_units & & cyl_units )
units_per_sector = cyl_units ;
2006-12-06 17:25:37 -06:00
else
2010-06-15 06:13:05 -05:00
units_per_sector = 1 ; /* in sectors */
2006-12-06 17:25:32 -06:00
}
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
}
2012-06-03 13:15:17 -05:00
void warn_alignment ( struct fdisk_context * cxt )
2012-04-28 17:02:45 -05:00
{
2010-02-04 08:02:16 -06:00
if ( nowarn )
2009-11-03 05:00:23 -06:00
return ;
2012-06-03 13:15:17 -05:00
if ( cxt - > sector_size ! = cxt - > phy_sector_size )
2010-02-04 08:02:16 -06:00
fprintf ( stderr , _ ( " \n "
2009-11-03 05:00:23 -06:00
" The device presents a logical sector size that is smaller than \n "
2010-02-04 08:02:16 -06:00
" the physical sector size. Aligning to a physical sector (or optimal \n "
" I/O) size boundary is recommended, or performance may be impacted. \n " ) ) ;
2009-11-03 05:00:23 -06:00
2010-06-14 13:08:50 -05:00
if ( dos_compatible_flag )
2010-02-04 08:02:16 -06:00
fprintf ( stderr , _ ( " \n "
" WARNING: DOS-compatible mode is deprecated. It's strongly recommended to \n "
2010-06-14 13:08:50 -05:00
" switch off the mode (with command 'c'). " ) ) ;
2009-11-03 05:00:23 -06:00
2010-06-14 13:08:50 -05:00
if ( display_in_cyl_units )
2010-02-15 07:39:30 -06:00
fprintf ( stderr , _ ( " \n "
" WARNING: cylinders as display units are deprecated. Use command 'u' to \n "
" change units to sectors. \n " ) ) ;
2009-11-03 05:00:23 -06:00
}
2009-11-03 04:28:55 -06:00
/*
* Sets LBA of the first partition
*/
void
2012-06-03 13:15:17 -05:00
update_sector_offset ( struct fdisk_context * cxt )
2009-11-03 04:28:55 -06:00
{
2012-07-26 09:04:24 -05:00
cxt - > grain = cxt - > io_size ;
2010-02-04 06:43:37 -06:00
2010-02-08 10:45:42 -06:00
if ( dos_compatible_flag )
2012-06-17 11:10:33 -05:00
sector_offset = cxt - > geom . sectors ; /* usually 63 sectors */
2010-02-08 10:45:42 -06:00
else {
2009-11-03 04:28:55 -06:00
/*
2010-02-04 06:43:37 -06:00
* Align the begin of partitions to :
*
* a ) topology
* a2 ) alignment offset
* a1 ) or physical sector ( minimal_io_size , aka " grain " )
*
* b ) or default to 1 MiB ( 2048 sectrors , Windows Vista default )
*
2010-02-15 09:46:05 -06:00
* c ) or for very small devices use 1 phy . sector
2009-11-03 04:28:55 -06:00
*/
2012-05-27 14:44:13 -05:00
sector_t x = 0 ;
2010-02-04 06:43:37 -06:00
2012-06-03 13:15:17 -05:00
if ( fdisk_dev_has_topology ( cxt ) ) {
if ( cxt - > alignment_offset )
x = cxt - > alignment_offset ;
else if ( cxt - > io_size > 2048 * 512 )
x = cxt - > io_size ;
2010-02-15 08:55:22 -06:00
}
/* default to 1MiB */
if ( ! x )
x = 2048 * 512 ;
2010-02-04 06:43:37 -06:00
2012-06-03 13:15:17 -05:00
sector_offset = x / cxt - > sector_size ;
2009-11-03 04:28:55 -06:00
2010-02-15 09:46:05 -06:00
/* don't use huge offset on small devices */
2012-06-03 13:15:20 -05:00
if ( cxt - > total_sectors < = sector_offset * 4 )
2012-06-03 13:15:17 -05:00
sector_offset = cxt - > phy_sector_size / cxt - > sector_size ;
2010-02-15 08:55:22 -06:00
/* use 1MiB grain always when possible */
2012-07-26 09:04:24 -05:00
if ( cxt - > grain < 2048 * 512 )
cxt - > grain = 2048 * 512 ;
2010-02-15 09:46:05 -06:00
/* don't use huge grain on small devices */
2012-07-26 09:04:24 -05:00
if ( cxt - > total_sectors < = ( cxt - > grain * 4 / cxt - > sector_size ) )
cxt - > grain = cxt - > phy_sector_size ;
2009-11-03 04:28:55 -06:00
}
}
2011-01-02 15:58:12 -06:00
static int is_partition_table_changed ( void )
{
int i ;
for ( i = 0 ; i < partitions ; i + + )
if ( ptes [ i ] . changed )
return 1 ;
return 0 ;
}
2011-01-05 09:50:47 -06:00
static void maybe_exit ( int rc , int * asked )
2011-01-02 15:58:12 -06:00
{
char line [ LINE_LENGTH ] ;
putchar ( ' \n ' ) ;
2011-01-05 09:50:47 -06:00
if ( asked )
* asked = 0 ;
2011-01-02 15:58:12 -06:00
if ( is_partition_table_changed ( ) | | MBRbuffer_changed ) {
fprintf ( stderr , _ ( " Do you really want to quit? " ) ) ;
if ( ! fgets ( line , LINE_LENGTH , stdin ) | | rpmatch ( line ) = = 1 )
exit ( rc ) ;
2011-01-05 09:50:47 -06:00
if ( asked )
* asked = 1 ;
2011-01-02 15:58:12 -06:00
} else
exit ( rc ) ;
}
2006-12-06 17:25:37 -06:00
/* read line; return 0 or first char */
int
2011-01-05 09:50:47 -06:00
read_line ( 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 ) ) {
2011-01-05 09:50:47 -06:00
maybe_exit ( 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 ;
}
2006-12-06 17:25:37 -06:00
char
read_char ( 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 */
2011-01-05 09:50:47 -06:00
} while ( ! read_line ( NULL ) ) ;
2006-12-06 17:25:32 -06:00
return * line_ptr ;
}
2006-12-06 17:25:37 -06:00
char
read_chars ( 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 */
rc = read_line ( & asked ) ;
} 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 )
read_chars ( _ ( " Partition type (type L to list all types): " ) ) ;
else
read_chars ( _ ( " Hex code (type L to list all codes): " ) ) ;
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 */
while ( read_chars ( ms ) ! = ' \n ' & & ! isdigit ( * line_ptr )
& & * 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
*/
if ( ! display_in_cyl_units )
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 ;
2012-06-03 13:15:17 -05:00
unit = cxt - > sector_size * units_per_sector ;
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
}
2006-12-06 17:25:43 -06:00
int
2012-06-03 13:15:17 -05:00
get_partition_dflt ( struct fdisk_context * cxt , int warn , int max , int dflt ) {
2006-12-06 17:25:43 -06:00
struct pte * pe ;
int i ;
2012-06-03 13:15:17 -05:00
i = read_int ( cxt , 1 , dflt , max , 0 , _ ( " Partition number " ) ) - 1 ;
2006-12-06 17:25:43 -06:00
pe = & ptes [ i ] ;
2006-12-06 17:25:32 -06:00
2012-11-25 22:25:49 -06:00
if ( warn & & ! fdisk_is_disklabel ( cxt , GPT ) ) {
if ( ( ! fdisk_is_disklabel ( cxt , SUN ) & &
! fdisk_is_disklabel ( cxt , SGI ) & & ! pe - > part_table - > sys_ind )
| | ( fdisk_is_disklabel ( cxt , SUN ) & &
2006-12-06 17:26:03 -06:00
( ! sunlabel - > partitions [ i ] . num_sectors | |
fdisk: many significant improvements and fixes to Sun label handling
1) Properly describe the exact layout and fields of the sun disk
label. Several fields were incorrectly mentioned and others
wrongly sized.
2) Properly set the version, sane, and num_partitions fields.
Because we weren't doing this, programs such as Solaris's format
and the Solaris kernel itself refused to recognize our disk labels
as valid.
3) Move SSWAP*() macros into fdisksunlabel.c as there is no reason
for them to be exposed to the rest of fdisk.
4) Kill the sun_predefined_drives array hack and assosciated code.
Instead size the disk and figure out the geometry properly just
like the SGI and MSDOS partition handling do, by means of the
HD_GETGEO ioctl() and disksize().
5) If the disk label read is found to not have the proper values
set in version, sane, or num_partitions, fix them, recompute the
label checksum, dirty the disk label, and let the user know what
we did and that the fixed values will be written out if they 'w'.
This gives users an easy way to fix up disk labels created by
disk labelling programs which had this bug.
6) Create a sun_sys_getid() function so that fdisk.c does not need
to reference the sun disk label details directly, just like the
SGI code does.
Signed-off-by: David S. Miller <davem@davemloft.net>
2007-06-29 17:50:21 -05:00
! sunlabel - > part_tags [ i ] . tag ) )
2012-11-25 22:25:49 -06:00
| | ( fdisk_is_disklabel ( cxt , SGI ) & &
( ! sgi_get_num_sectors ( cxt , i ) ) ) )
2006-12-06 17:26:03 -06:00
fprintf ( stderr ,
_ ( " Warning: partition %d has empty type \n " ) ,
i + 1 ) ;
}
2006-12-06 17:25:32 -06:00
return i ;
}
2010-04-28 03:10:39 -05:00
int
2012-06-03 13:15:17 -05:00
get_partition ( struct fdisk_context * cxt , int warn , int max ) {
return get_partition_dflt ( cxt , warn , max , 0 ) ;
2010-04-28 03:10:39 -05:00
}
2011-12-15 13:02:45 -06:00
/* User partition selection unless one partition only is available */
2006-12-06 17:26:03 -06:00
static int
2012-06-03 13:15:17 -05:00
get_existing_partition ( struct fdisk_context * cxt , int warn , int max ) {
2006-12-06 17:26:03 -06:00
int pno = - 1 ;
int i ;
2012-11-25 22:25:49 -06:00
if ( ! fdisk_is_disklabel ( cxt , DOS ) )
2011-12-15 13:02:45 -06:00
goto not_implemented ;
2006-12-06 17:26:03 -06:00
for ( i = 0 ; i < max ; i + + ) {
struct pte * pe = & ptes [ i ] ;
struct partition * p = pe - > part_table ;
if ( p & & ! is_cleared_partition ( p ) ) {
if ( pno > = 0 )
goto not_unique ;
pno = i ;
}
}
2011-07-03 05:01:21 -05:00
2006-12-06 17:26:03 -06:00
if ( pno > = 0 ) {
printf ( _ ( " Selected partition %d \n " ) , pno + 1 ) ;
return pno ;
}
printf ( _ ( " No partition is defined yet! \n " ) ) ;
return - 1 ;
2011-12-15 13:02:45 -06:00
not_implemented :
not_unique :
2012-06-03 13:15:17 -05:00
return get_partition ( cxt , warn , max ) ;
2006-12-06 17:26:03 -06:00
}
2007-05-30 10:41:14 -05:00
const char *
2011-11-14 07:47:17 -06:00
str_units ( int n )
{
if ( display_in_cyl_units )
return P_ ( " cylinder " , " cylinders " , n ) ;
return P_ ( " sector " , " sectors " , n ) ;
2006-12-06 17:25:32 -06:00
}
2012-06-17 11:10:33 -05:00
void change_units ( struct fdisk_context * cxt )
2006-12-06 17:25:32 -06:00
{
2006-12-06 17:25:39 -06:00
display_in_cyl_units = ! display_in_cyl_units ;
2012-06-17 11:10:33 -05:00
update_units ( cxt ) ;
2010-06-16 03:52:20 -05:00
if ( display_in_cyl_units )
printf ( _ ( " Changing display/entry units to cylinders (DEPRECATED!) \n " ) ) ;
else
printf ( _ ( " Changing display/entry units to sectors \n " ) ) ;
2006-12-06 17:25:32 -06:00
}
2006-12-06 17:25:43 -06:00
static void
toggle_active ( int i ) {
struct pte * pe = & ptes [ i ] ;
struct partition * p = pe - > part_table ;
2006-12-06 17:25:32 -06:00
2006-12-06 17:25:35 -06:00
if ( IS_EXTENDED ( p - > sys_ind ) & & ! p - > boot_ind )
2006-12-06 17:25:32 -06:00
fprintf ( stderr ,
2006-12-06 17:25:39 -06:00
_ ( " WARNING: Partition %d is an extended partition \n " ) ,
2006-12-06 17:25:32 -06:00
i + 1 ) ;
2006-12-06 17:25:43 -06:00
p - > boot_ind = ( p - > boot_ind ? 0 : ACTIVE_FLAG ) ;
pe - > changed = 1 ;
2006-12-06 17:25:32 -06:00
}
2006-12-06 17:25:43 -06:00
static void
2012-06-03 13:15:17 -05:00
toggle_dos_compatibility_flag ( struct fdisk_context * cxt ) {
2006-12-06 17:25:32 -06:00
dos_compatible_flag = ~ dos_compatible_flag ;
2009-11-03 04:28:55 -06:00
if ( dos_compatible_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-06-03 13:15:17 -05:00
update_sector_offset ( 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
{
2012-09-25 03:23:36 -05:00
int i ;
struct fdisk_parttype * t , * org_t ;
2006-12-06 17:25:32 -06:00
2012-06-03 13:15:17 -05:00
i = get_existing_partition ( cxt , 0 , partitions ) ;
2006-12-06 17:26:03 -06:00
if ( i = = - 1 )
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 )
2006-12-06 17:25:39 -06:00
printf ( _ ( " Partition %d 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 {
printf ( _ ( " Type of partition %d is unchanged: %s \n " ) ,
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
}
/* check_consistency() and long2chs() added Sat Mar 6 12:28:16 1993,
* faith @ cs . unc . edu , based on code fragments from pfdisk by Gordon W . Ross ,
* Jan . 1990 ( version 1.2 .1 by Gordon W . Ross Aug . 1990 ; Modified by S .
* Lubkin Oct . 1991 ) . */
2006-12-06 17:26:12 -06:00
static void
2012-06-17 11:10:33 -05:00
long2chs ( struct fdisk_context * cxt , unsigned long ls ,
unsigned int * c , unsigned int * h , unsigned int * s ) {
int spc = cxt - > geom . heads * cxt - > geom . sectors ;
2006-12-06 17:25:32 -06:00
* c = ls / spc ;
ls = ls % spc ;
2012-06-17 11:10:33 -05:00
* h = ls / cxt - > geom . sectors ;
* s = ls % cxt - > geom . sectors + 1 ; /* sectors count from 1 */
2006-12-06 17:25:32 -06:00
}
2012-07-24 02:54:52 -05:00
void check_consistency ( struct fdisk_context * cxt , struct partition * p , int partition )
{
2006-12-06 17:26:12 -06:00
unsigned int pbc , pbh , pbs ; /* physical beginning c, h, s */
unsigned int pec , peh , pes ; /* physical ending c, h, s */
unsigned int lbc , lbh , lbs ; /* logical beginning c, h, s */
unsigned int lec , leh , les ; /* logical ending c, h, s */
2006-12-06 17:25:32 -06:00
2010-02-04 08:02:16 -06:00
if ( ! dos_compatible_flag )
return ;
2012-06-17 11:10:33 -05:00
if ( ! cxt - > geom . heads | | ! cxt - > geom . sectors | | ( partition > = 4 ) )
2006-12-06 17:25:32 -06:00
return ; /* do not check extended partitions */
/* physical beginning c, h, s */
2006-12-06 17:25:34 -06:00
pbc = ( p - > cyl & 0xff ) | ( ( p - > sector < < 2 ) & 0x300 ) ;
2006-12-06 17:25:32 -06:00
pbh = p - > head ;
pbs = p - > sector & 0x3f ;
/* physical ending c, h, s */
2006-12-06 17:25:34 -06:00
pec = ( p - > end_cyl & 0xff ) | ( ( p - > end_sector < < 2 ) & 0x300 ) ;
2006-12-06 17:25:32 -06:00
peh = p - > end_head ;
pes = p - > end_sector & 0x3f ;
/* compute logical beginning (c, h, s) */
2012-06-17 11:10:33 -05:00
long2chs ( cxt , get_start_sect ( p ) , & lbc , & lbh , & lbs ) ;
2006-12-06 17:25:32 -06:00
/* compute logical ending (c, h, s) */
2012-06-17 11:10:33 -05:00
long2chs ( cxt , get_start_sect ( p ) + get_nr_sects ( p ) - 1 , & lec , & leh , & les ) ;
2006-12-06 17:25:32 -06:00
/* Same physical / logical beginning? */
2012-06-17 11:10:33 -05:00
if ( cxt - > geom . cylinders < = 1024 & & ( pbc ! = lbc | | pbh ! = lbh | | pbs ! = lbs ) ) {
2006-12-06 17:25:39 -06:00
printf ( _ ( " Partition %d has different physical/logical "
" beginnings (non-Linux?): \n " ) , partition + 1 ) ;
printf ( _ ( " phys=(%d, %d, %d) " ) , pbc , pbh , pbs ) ;
printf ( _ ( " logical=(%d, %d, %d) \n " ) , lbc , lbh , lbs ) ;
2006-12-06 17:25:32 -06:00
}
/* Same physical / logical ending? */
2012-06-17 11:10:33 -05:00
if ( cxt - > geom . cylinders < = 1024 & & ( pec ! = lec | | peh ! = leh | | pes ! = les ) ) {
2006-12-06 17:25:39 -06:00
printf ( _ ( " Partition %d has different physical/logical "
" endings: \n " ) , partition + 1 ) ;
printf ( _ ( " phys=(%d, %d, %d) " ) , pec , peh , pes ) ;
printf ( _ ( " logical=(%d, %d, %d) \n " ) , lec , leh , les ) ;
2006-12-06 17:25:32 -06:00
}
/* Ending on cylinder boundary? */
2012-06-17 11:10:33 -05:00
if ( peh ! = ( cxt - > geom . heads - 1 ) | | pes ! = cxt - > geom . sectors ) {
2006-12-06 17:26:08 -06:00
printf ( _ ( " Partition %i does not end on cylinder boundary. \n " ) ,
2006-12-06 17:25:32 -06:00
partition + 1 ) ;
}
}
2012-07-24 02:54:52 -05:00
void check_alignment ( struct fdisk_context * cxt , sector_t lba , int partition )
2009-11-03 05:09:36 -06:00
{
2012-07-23 16:09:41 -05:00
if ( ! lba_is_phy_aligned ( cxt , lba ) )
2010-02-04 08:02:16 -06:00
printf ( _ ( " Partition %i does not start on physical sector boundary. \n " ) ,
2009-11-03 05:09:36 -06:00
partition + 1 ) ;
}
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-07-26 09:04:27 -05:00
if ( dos_compatible_flag )
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 " ) ,
2006-12-06 17:26:03 -06:00
str_units ( PLURAL ) ,
2012-06-03 13:15:17 -05:00
units_per_sector , cxt - > sector_size , units_per_sector * 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-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
}
2006-12-06 17:25:43 -06:00
/*
* Check whether partition entries are ordered by their starting positions .
* Return 0 if OK . Return i if partition i should have been earlier .
* Two separate checks : primary and logical partitions .
*/
static int
wrong_p_order ( int * prev ) {
struct pte * pe ;
struct partition * p ;
2006-12-06 17:26:12 -06:00
unsigned int last_p_start_pos = 0 , p_start_pos ;
2006-12-06 17:25:43 -06:00
int i , last_i = 0 ;
for ( i = 0 ; i < partitions ; i + + ) {
if ( i = = 4 ) {
last_i = 4 ;
last_p_start_pos = 0 ;
}
pe = & ptes [ i ] ;
if ( ( p = pe - > part_table ) - > sys_ind ) {
p_start_pos = get_partition_start ( pe ) ;
if ( last_p_start_pos > p_start_pos ) {
if ( prev )
* prev = last_i ;
return i ;
}
last_p_start_pos = p_start_pos ;
last_i = i ;
}
}
return 0 ;
}
2006-12-06 17:25:48 -06:00
/*
* Fix the chain of logicals .
* extended_offset is unchanged , the set of sectors used is unchanged
* The chain is sorted so that sectors increase , and so that
* starting sectors increase .
*
2012-04-19 17:10:44 -05:00
* After this it may still be that cfdisk doesn ' t like the table .
2006-12-06 17:25:48 -06:00
* ( This is because cfdisk considers expanded parts , from link to
* end of partition , and these may still overlap . )
* Now
* sfdisk / dev / hda > ohda ; sfdisk / dev / hda < ohda
* may help .
*/
static void
fix_chain_of_logicals ( void ) {
int j , oj , ojj , sj , sjj ;
struct partition * pj , * pjj , tmp ;
/* Stage 1: sort sectors but leave sector of part 4 */
/* (Its sector is the global extended_offset.) */
stage1 :
2006-12-06 17:25:58 -06:00
for ( j = 5 ; j < partitions - 1 ; j + + ) {
2006-12-06 17:25:48 -06:00
oj = ptes [ j ] . offset ;
ojj = ptes [ j + 1 ] . offset ;
if ( oj > ojj ) {
ptes [ j ] . offset = ojj ;
ptes [ j + 1 ] . offset = oj ;
pj = ptes [ j ] . part_table ;
set_start_sect ( pj , get_start_sect ( pj ) + oj - ojj ) ;
pjj = ptes [ j + 1 ] . part_table ;
set_start_sect ( pjj , get_start_sect ( pjj ) + ojj - oj ) ;
set_start_sect ( ptes [ j - 1 ] . ext_pointer ,
ojj - extended_offset ) ;
set_start_sect ( ptes [ j ] . ext_pointer ,
oj - extended_offset ) ;
goto stage1 ;
}
}
/* Stage 2: sort starting sectors */
stage2 :
2006-12-06 17:25:58 -06:00
for ( j = 4 ; j < partitions - 1 ; j + + ) {
2006-12-06 17:25:48 -06:00
pj = ptes [ j ] . part_table ;
pjj = ptes [ j + 1 ] . part_table ;
sj = get_start_sect ( pj ) ;
sjj = get_start_sect ( pjj ) ;
oj = ptes [ j ] . offset ;
ojj = ptes [ j + 1 ] . offset ;
if ( oj + sj > ojj + sjj ) {
tmp = * pj ;
* pj = * pjj ;
* pjj = tmp ;
set_start_sect ( pj , ojj + sjj - oj ) ;
set_start_sect ( pjj , oj + sj - ojj ) ;
goto stage2 ;
}
}
/* Probably something was changed */
2006-12-06 17:25:58 -06:00
for ( j = 4 ; j < partitions ; j + + )
2006-12-06 17:25:48 -06:00
ptes [ j ] . changed = 1 ;
}
2006-12-06 17:25:43 -06:00
static void
fix_partition_table_order ( void ) {
2006-12-06 17:25:48 -06:00
struct pte * pei , * pek ;
2006-12-06 17:25:43 -06:00
int i , k ;
2006-12-06 17:25:58 -06:00
if ( ! wrong_p_order ( NULL ) ) {
2006-12-06 17:25:43 -06:00
printf ( _ ( " Nothing to do. Ordering is correct already. \n \n " ) ) ;
return ;
}
2006-12-06 17:25:48 -06:00
while ( ( i = wrong_p_order ( & k ) ) ! = 0 & & i < 4 ) {
2006-12-06 17:25:43 -06:00
/* partition i should have come earlier, move it */
2006-12-06 17:25:48 -06:00
/* We have to move data in the MBR */
struct partition * pi , * pk , * pe , pbuf ;
2006-12-06 17:25:43 -06:00
pei = & ptes [ i ] ;
pek = & ptes [ k ] ;
2006-12-06 17:25:48 -06:00
pe = pei - > ext_pointer ;
pei - > ext_pointer = pek - > ext_pointer ;
pek - > ext_pointer = pe ;
2006-12-06 17:25:43 -06:00
2006-12-06 17:25:48 -06:00
pi = pei - > part_table ;
pk = pek - > part_table ;
2006-12-06 17:25:43 -06:00
2006-12-06 17:25:48 -06:00
memmove ( & pbuf , pi , sizeof ( struct partition ) ) ;
memmove ( pi , pk , sizeof ( struct partition ) ) ;
memmove ( pk , & pbuf , sizeof ( struct partition ) ) ;
2006-12-06 17:25:43 -06:00
pei - > changed = pek - > changed = 1 ;
}
2006-12-06 17:25:48 -06:00
if ( i )
fix_chain_of_logicals ( ) ;
2008-10-03 01:52:35 -05:00
printf ( _ ( " Done. \n " ) ) ;
2006-12-06 17:25:48 -06:00
2006-12-06 17:25:43 -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 )
{
2006-12-06 17:25:32 -06:00
struct partition * p ;
2006-12-06 17:25:35 -06:00
int i , w ;
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 ;
}
2006-12-06 17:26:24 -06:00
if ( is_garbage_table ( ) ) {
printf ( _ ( " This doesn't look like a partition table \n "
" Probably you selected the wrong device. \n \n " ) ) ;
}
2006-12-06 17:25:37 -06:00
/* Heuristic: we list partition 3 of /dev/foo as /dev/foo3,
but if the device name ends in a digit , say / dev / foo1 ,
then the partition is called / dev / foo1p3 . */
2012-05-21 15:28:03 -05:00
w = strlen ( cxt - > dev_path ) ;
if ( w & & isdigit ( cxt - > dev_path [ w - 1 ] ) )
2006-12-06 17:25:43 -06:00
w + + ;
2006-12-06 17:25:32 -06:00
if ( w < 5 )
w = 5 ;
2006-12-06 17:25:39 -06:00
2006-12-06 17:26:12 -06:00
printf ( _ ( " %*s Boot Start End Blocks Id System \n " ) ,
2006-12-06 17:25:43 -06:00
w + 1 , _ ( " Device " ) ) ;
2006-12-06 17:25:35 -06:00
2006-12-06 17:26:03 -06:00
for ( i = 0 ; i < partitions ; i + + ) {
2006-12-06 17:25:43 -06:00
struct pte * pe = & ptes [ i ] ;
p = pe - > part_table ;
2006-12-06 17:25:49 -06:00
if ( p & & ! is_cleared_partition ( p ) ) {
2006-12-06 17:25:35 -06:00
unsigned int psects = get_nr_sects ( p ) ;
2006-12-06 17:25:37 -06:00
unsigned int pblocks = psects ;
unsigned int podd = 0 ;
2012-09-25 03:23:36 -05:00
struct fdisk_parttype * type =
fdisk_get_parttype_from_code ( cxt , p - > sys_ind ) ;
2006-12-06 17:25:37 -06:00
2012-06-03 13:15:17 -05:00
if ( cxt - > sector_size < 1024 ) {
pblocks / = ( 1024 / cxt - > sector_size ) ;
podd = psects % ( 1024 / cxt - > sector_size ) ;
2006-12-06 17:25:37 -06:00
}
2012-06-03 13:15:17 -05:00
if ( cxt - > sector_size > 1024 )
pblocks * = ( cxt - > sector_size / 1024 ) ;
2006-12-06 17:25:35 -06:00
printf (
2006-12-06 17:26:12 -06:00
" %s %c %11lu %11lu %11lu%c %2x %s \n " ,
2012-05-21 15:28:03 -05:00
partname ( cxt - > dev_path , i + 1 , w + 2 ) ,
2006-12-06 17:25:33 -06:00
/* boot flag */ ! p - > boot_ind ? ' ' : p - > boot_ind = = ACTIVE_FLAG
2006-12-06 17:25:32 -06:00
? ' * ' : ' ? ' ,
2006-12-06 17:26:12 -06:00
/* start */ ( unsigned long ) cround ( get_partition_start ( pe ) ) ,
/* end */ ( unsigned long ) cround ( get_partition_start ( pe ) + psects
2006-12-06 17:25:35 -06:00
- ( psects ? 1 : 0 ) ) ,
2006-12-06 17:26:12 -06:00
/* odd flag on end */ ( unsigned long ) pblocks , podd ? ' + ' : ' ' ,
2006-12-06 17:25:33 -06:00
/* type id */ p - > sys_ind ,
2012-09-25 03:23:36 -05:00
/* type name */ type ? type - > name : _ ( " Unknown " ) ) ;
2012-06-17 11:10:33 -05:00
check_consistency ( cxt , p , i ) ;
2012-06-03 13:15:17 -05:00
check_alignment ( cxt , get_partition_start ( pe ) , i ) ;
2006-12-06 17:25:32 -06:00
}
2006-12-06 17:25:35 -06:00
}
2006-12-06 17:25:46 -06:00
2006-12-06 17:25:43 -06:00
/* Is partition table in disk order? It need not be, but... */
/* partition table entries are not checked for correct order if this
is a sgi , sun or aix labeled disk . . . */
2012-11-25 22:25:49 -06:00
if ( fdisk_is_disklabel ( cxt , DOS ) & & wrong_p_order ( NULL ) ) {
2006-12-06 17:25:43 -06:00
printf ( _ ( " \n Partition table entries are not in disk order \n " ) ) ;
}
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
x_list_table ( struct fdisk_context * cxt , int extend ) {
2006-12-06 17:25:43 -06:00
struct pte * pe ;
struct partition * p ;
2006-12-06 17:25:32 -06:00
int i ;
2012-06-17 11:10:33 -05:00
printf ( _ ( " \n Disk %s: %d heads, %llu sectors, %llu cylinders \n \n " ) ,
cxt - > dev_path , cxt - > geom . heads , cxt - > geom . sectors , cxt - > geom . cylinders ) ;
2006-12-06 17:26:12 -06:00
printf ( _ ( " Nr AF Hd Sec Cyl Hd Sec Cyl Start Size ID \n " ) ) ;
2006-12-06 17:25:43 -06:00
for ( i = 0 ; i < partitions ; i + + ) {
pe = & ptes [ i ] ;
p = ( extend ? pe - > ext_pointer : pe - > part_table ) ;
if ( p ! = NULL ) {
2007-05-30 10:10:43 -05:00
printf ( " %2d %02x%4d%4d%5d%4d%4d%5d%11lu%11lu %02x \n " ,
2006-12-06 17:25:32 -06:00
i + 1 , p - > boot_ind , p - > head ,
sector ( p - > sector ) ,
cylinder ( p - > sector , p - > cyl ) , p - > end_head ,
sector ( p - > end_sector ) ,
cylinder ( p - > end_sector , p - > end_cyl ) ,
2007-05-30 10:10:43 -05:00
( unsigned long ) get_start_sect ( p ) ,
( unsigned long ) get_nr_sects ( p ) , p - > sys_ind ) ;
2009-11-03 05:09:36 -06:00
if ( p - > sys_ind ) {
2012-06-17 11:10:33 -05:00
check_consistency ( cxt , p , i ) ;
2012-06-03 13:15:17 -05:00
check_alignment ( cxt , get_partition_start ( pe ) , i ) ;
2009-11-03 05:09:36 -06:00
}
2006-12-06 17:25:32 -06:00
}
2006-12-06 17:25:43 -06:00
}
2006-12-06 17:25:32 -06:00
}
2012-05-27 14:44:13 -05:00
void fill_bounds ( sector_t * first , sector_t * last )
2012-05-06 07:10:18 -05:00
{
2006-12-06 17:25:32 -06:00
int i ;
2006-12-06 17:25:43 -06:00
struct pte * pe = & ptes [ 0 ] ;
struct partition * p ;
2006-12-06 17:25:32 -06:00
2006-12-06 17:25:43 -06:00
for ( i = 0 ; i < partitions ; pe + + , i + + ) {
p = pe - > part_table ;
2006-12-06 17:25:35 -06:00
if ( ! p - > sys_ind | | IS_EXTENDED ( p - > sys_ind ) ) {
2006-12-06 17:25:37 -06:00
first [ i ] = 0xffffffff ;
2006-12-06 17:25:32 -06:00
last [ i ] = 0 ;
2006-12-06 17:25:35 -06:00
} else {
2006-12-06 17:25:43 -06:00
first [ i ] = get_partition_start ( pe ) ;
2006-12-06 17:25:37 -06:00
last [ i ] = first [ i ] + get_nr_sects ( p ) - 1 ;
2006-12-06 17:25:32 -06:00
}
2006-12-06 17:25:35 -06:00
}
2006-12-06 17:25:32 -06:00
}
2012-07-24 02:54:52 -05:00
void check ( struct fdisk_context * cxt , int n ,
unsigned int h , unsigned int s , unsigned int c ,
unsigned int start )
{
2006-12-06 17:26:12 -06:00
unsigned int total , real_s , real_c ;
2006-12-06 17:25:32 -06:00
real_s = sector ( s ) - 1 ;
real_c = cylinder ( s , c ) ;
2012-06-17 11:10:33 -05:00
total = ( real_c * cxt - > geom . sectors + real_s ) * cxt - > geom . heads + h ;
2006-12-06 17:25:32 -06:00
if ( ! total )
2006-12-06 17:25:39 -06:00
fprintf ( stderr , _ ( " Warning: partition %d contains sector 0 \n " ) , n ) ;
2012-06-17 11:10:33 -05:00
if ( h > = cxt - > geom . heads )
2006-12-06 17:25:32 -06:00
fprintf ( stderr ,
2006-12-06 17:25:39 -06:00
_ ( " Partition %d: head %d greater than maximum %d \n " ) ,
2012-06-17 11:10:33 -05:00
n , h + 1 , cxt - > geom . heads ) ;
if ( real_s > = cxt - > geom . sectors )
2006-12-06 17:25:39 -06:00
fprintf ( stderr , _ ( " Partition %d: sector %d greater than "
2012-06-17 11:10:33 -05:00
" maximum %llu \n " ) , n , s , cxt - > geom . sectors ) ;
if ( real_c > = cxt - > geom . cylinders )
2006-12-06 17:25:39 -06:00
fprintf ( stderr , _ ( " Partitions %d: cylinder %d greater than "
2012-06-17 11:10:33 -05:00
" maximum %llu \n " ) , n , real_c + 1 , cxt - > geom . cylinders ) ;
if ( cxt - > geom . cylinders < = 1024 & & start ! = total )
2006-12-06 17:25:32 -06:00
fprintf ( stderr ,
2006-12-06 17:25:39 -06:00
_ ( " Partition %d: previous sectors %d disagrees with "
" total %d \n " ) , n , start , total ) ;
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
{
2012-07-24 02:34:22 -05:00
int partnum = 0 ;
2006-12-06 17:25:35 -06:00
2012-07-24 02:34:22 -05:00
if ( warn_geometry ( cxt ) )
2006-12-06 17:25:49 -06:00
return ;
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-24 02:34:22 -05:00
partnum = get_partition ( cxt , 0 , partitions ) ;
2007-06-27 16:49:56 -05:00
2012-09-26 07:14:54 -05:00
fdisk_add_partition ( cxt , partnum , 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 )
{
2006-12-06 17:25:32 -06:00
int i ;
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 ) ;
2006-12-06 17:25:35 -06:00
else for ( i = 3 ; i < partitions ; i + + )
2012-06-03 13:15:17 -05:00
print_buffer ( cxt , ptes [ i ] . sectorbuffer ) ;
2006-12-06 17:25:32 -06:00
}
2006-12-06 17:25:43 -06:00
static void
2012-06-03 13:15:17 -05:00
move_begin ( struct fdisk_context * cxt , int i ) {
2006-12-06 17:25:43 -06:00
struct pte * pe = & ptes [ i ] ;
struct partition * p = pe - > part_table ;
2010-04-28 07:40:46 -05:00
unsigned int new , free_start , curr_start , last ;
int x ;
2006-12-06 17:25:32 -06:00
2012-06-17 11:10:33 -05:00
if ( warn_geometry ( cxt ) )
2006-12-06 17:25:32 -06:00
return ;
2006-12-06 17:25:35 -06:00
if ( ! p - > sys_ind | | ! get_nr_sects ( p ) | | IS_EXTENDED ( p - > sys_ind ) ) {
2006-12-06 17:25:39 -06:00
printf ( _ ( " Partition %d has no data area \n " ) , i + 1 ) ;
2006-12-06 17:25:32 -06:00
return ;
}
2010-04-28 07:40:46 -05:00
/* the default start is at the second sector of the disk or at the
* second sector of the extended partition
*/
free_start = pe - > offset ? pe - > offset + 1 : 1 ;
curr_start = get_partition_start ( pe ) ;
/* look for a free space before the current start of the partition */
for ( x = 0 ; x < partitions ; x + + ) {
unsigned int end ;
struct pte * prev_pe = & ptes [ x ] ;
struct partition * prev_p = prev_pe - > part_table ;
if ( ! prev_p )
continue ;
end = get_partition_start ( prev_pe ) + get_nr_sects ( prev_p ) ;
if ( ! is_cleared_partition ( prev_p ) & &
end > free_start & & end < = curr_start )
free_start = end ;
}
last = get_partition_start ( pe ) + get_nr_sects ( p ) - 1 ;
2012-06-03 13:15:17 -05:00
new = read_int ( cxt , free_start , curr_start , last , free_start ,
2006-12-06 17:25:43 -06:00
_ ( " New beginning of data " ) ) - pe - > offset ;
2006-12-06 17:25:32 -06:00
2006-12-06 17:25:35 -06:00
if ( new ! = get_nr_sects ( p ) ) {
2010-04-28 07:40:46 -05:00
unsigned int sects = get_nr_sects ( p ) + get_start_sect ( p ) - new ;
set_nr_sects ( p , sects ) ;
2006-12-06 17:25:35 -06:00
set_start_sect ( p , new ) ;
2006-12-06 17:25:43 -06:00
pe - > changed = 1 ;
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 ;
2006-12-06 17:25:32 -06:00
while ( 1 ) {
putchar ( ' \n ' ) ;
2006-12-06 17:25:43 -06:00
c = tolower ( read_char ( _ ( " Expert command (m for help): " ) ) ) ;
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 ) )
2012-06-03 13:15:17 -05:00
sun_set_alt_cyl ( cxt ) ;
2006-12-06 17:25:35 -06:00
break ;
case ' b ' :
2012-11-25 22:25:49 -06:00
if ( fdisk_is_disklabel ( cxt , DOS ) )
2012-06-03 13:15:17 -05:00
move_begin ( cxt , get_partition ( cxt , 0 , partitions ) ) ;
2006-12-06 17:25:35 -06:00
break ;
case ' c ' :
2012-06-17 11:10:33 -05:00
user_cylinders = cxt - > geom . cylinders =
read_int ( cxt , 1 , cxt - > geom . cylinders , 1048576 , 0 ,
2006-12-06 17:25:43 -06:00
_ ( " Number of cylinders " ) ) ;
2012-11-25 22:25:49 -06:00
if ( fdisk_is_disklabel ( cxt , SUN ) )
2012-06-17 11:10:33 -05:00
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 ) )
2012-06-03 13:15:17 -05:00
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 ) )
x_list_table ( 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 ) )
2006-12-06 17:25:43 -06:00
fix_partition_table_order ( ) ;
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-06-17 11:10:33 -05:00
user_heads = cxt - > geom . heads = read_int ( cxt , 1 , cxt - > geom . heads , 256 , 0 ,
2006-12-06 17:25:39 -06:00
_ ( " Number of heads " ) ) ;
2012-06-17 11:10:33 -05:00
update_units ( cxt ) ;
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 ) )
2012-06-03 13:15:17 -05:00
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 ) )
2012-06-03 13:15:17 -05:00
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
2012-05-27 14:44:04 -05:00
x_list_table ( 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-06-17 11:10:33 -05:00
user_sectors = cxt - > geom . sectors = read_int ( cxt , 1 , cxt - > geom . sectors , 63 , 0 ,
2006-12-06 17:25:39 -06:00
_ ( " Number of sectors " ) ) ;
2009-11-03 04:28:55 -06:00
if ( dos_compatible_flag )
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-06-03 13:15:17 -05:00
update_sector_offset ( cxt ) ;
2012-06-17 11:10:33 -05:00
update_units ( cxt ) ;
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 ) )
2012-06-03 13:15:17 -05:00
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-06-03 13:15:17 -05:00
static void print_partition_table_from_option ( char * device , unsigned long sector_size )
2011-12-15 13:02:40 -06:00
{
2012-07-23 03:11:08 -05:00
struct fdisk_context * cxt ;
2006-12-06 17:25:49 -06:00
2012-07-23 03:11:08 -05:00
cxt = fdisk_new_context_from_filename ( device , 1 ) ; /* read-only */
2012-05-21 15:28:03 -05:00
if ( ! cxt )
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 */
fdisk_context_force_sector_size ( cxt , sector_size ) ;
2012-07-23 06:57:58 -05:00
if ( user_cylinders | | user_heads | | user_sectors )
fdisk_context_set_user_geometry ( cxt , user_cylinders ,
2012-07-23 03:11:08 -05:00
user_heads , user_sectors ) ;
2012-07-23 04:08:26 -05:00
if ( ! fdisk_dev_has_disklabel ( cxt ) ) {
/*
* Try BSD - - TODO : move to list_table ( ) too
*/
2012-05-27 14:44:04 -05:00
list_disk_geometry ( cxt ) ;
2012-11-25 22:25:49 -06:00
if ( ! fdisk_is_disklabel ( cxt , AIX ) & &
! fdisk_is_disklabel ( cxt , MAC ) )
2012-05-27 14:44:04 -05:00
btrydev ( cxt ) ;
2012-11-25 22:25:49 -06:00
} else
2012-05-27 14:44:04 -05:00
list_table ( cxt , 0 ) ;
2012-07-23 04:08:26 -05:00
2012-05-21 15:28:03 -05:00
fdisk_free_context ( cxt ) ;
2012-05-23 04:24:04 -05:00
cxt = NULL ;
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-06-03 13:15:17 -05:00
print_all_partition_table_from_option ( 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-06-03 13:15:17 -05:00
print_partition_table_from_option ( 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 ;
2007-05-31 07:31:51 -05:00
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 ) ;
2011-11-11 04:12:09 -06:00
/* If we return we may want to make an empty DOS label? */
2012-11-25 22:25:49 -06:00
cxt - > disklabel = FDISK_DISKLABEL_DOS ;
2011-11-11 04:12:09 -06:00
}
while ( 1 ) {
putchar ( ' \n ' ) ;
c = tolower ( read_char ( _ ( " Command (m for help): " ) ) ) ;
switch ( c ) {
case ' a ' :
2012-11-25 22:25:49 -06:00
if ( fdisk_is_disklabel ( cxt , DOS ) )
2012-06-03 13:15:17 -05:00
toggle_active ( get_partition ( cxt , 1 , partitions ) ) ;
2012-11-25 22:25:49 -06:00
else if ( fdisk_is_disklabel ( cxt , SUN ) )
2012-06-17 11:10:07 -05:00
toggle_sunflags ( cxt , get_partition ( cxt , 1 , partitions ) ,
2011-11-11 04:12:09 -06:00
SUN_FLAG_UNMNT ) ;
2012-11-25 22:25:49 -06:00
else if ( fdisk_is_disklabel ( cxt , SGI ) )
2012-06-17 11:10:07 -05:00
sgi_set_bootpartition ( cxt ,
2012-06-03 13:15:17 -05:00
get_partition ( cxt , 1 , partitions ) ) ;
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 ) ) {
cxt - > disklabel = FDISK_DISKLABEL_OSF ;
2012-05-27 14:44:04 -05:00
bsd_command_prompt ( cxt ) ;
2012-11-25 22:25:49 -06:00
cxt - > disklabel = FDISK_DISKLABEL_DOS ;
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 ) ;
2012-11-25 22:25:49 -06:00
else if ( fdisk_is_disklabel ( cxt , SUN ) )
2012-06-17 11:10:07 -05:00
toggle_sunflags ( cxt , get_partition ( cxt , 1 , partitions ) ,
2011-11-11 04:12:09 -06:00
SUN_FLAG_RONLY ) ;
2012-11-25 22:25:49 -06:00
else if ( fdisk_is_disklabel ( cxt , SGI ) )
2012-06-17 11:10:07 -05:00
sgi_set_swappartition ( cxt ,
2012-06-03 13:15:17 -05:00
get_partition ( cxt , 1 , partitions ) ) ;
2011-11-11 04:12:09 -06:00
else
unknown_command ( c ) ;
break ;
case ' d ' :
2012-06-03 13:15:17 -05:00
delete_partition ( cxt , get_existing_partition ( cxt , 1 , partitions ) ) ;
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 ;
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 ' :
2012-06-17 11:10:33 -05:00
change_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-05-27 14:44:04 -05:00
struct fdisk_context * cxt = NULL ;
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
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:37 -06:00
sector_offset = 2 ;
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 ' :
2010-06-16 03:52:20 -05:00
dos_compatible_flag = 0 ; /* default */
if ( optarg & & ! strcmp ( optarg , " =dos " ) )
dos_compatible_flag = ~ 0 ;
else if ( optarg & & strcmp ( optarg , " =nondos " ) )
2011-01-23 15:51:20 -06:00
usage ( stderr ) ;
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 ' :
2010-06-16 03:52:20 -05:00
display_in_cyl_units = 0 ; /* default */
if ( optarg & & strcmp ( optarg , " =cylinders " ) = = 0 )
display_in_cyl_units = ! display_in_cyl_units ;
else if ( optarg & & strcmp ( optarg , " =sectors " ) )
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
fdisk_init_debug ( 0 ) ;
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-06-03 13:15:17 -05:00
print_partition_table_from_option ( argv [ k ] , sector_size ) ;
2011-12-15 13:02:41 -06:00
} else
2012-06-03 13:15:17 -05:00
print_all_partition_table_from_option ( 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-07-15 01:58:51 -05:00
cxt = fdisk_new_context_from_filename ( argv [ optind ] , 0 ) ;
if ( ! cxt )
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-07-23 03:11:08 -05:00
fdisk_context_force_sector_size ( cxt , sector_size ) ;
2012-07-23 06:57:58 -05:00
if ( user_cylinders | | user_heads | | user_sectors )
fdisk_context_set_user_geometry ( cxt , user_cylinders ,
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-06-03 13:15:34 -05:00
if ( ! fdisk_dev_sectsz_is_default ( cxt ) )
printf ( _ ( " Note: sector size is %ld (not %d) \n " ) ,
cxt - > sector_size , DEFAULT_SECTOR_SIZE ) ;
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
2006-12-06 17:25:37 -06:00
return 0 ;
2006-12-06 17:25:32 -06:00
}